diff --git a/src/addons/outlook/manifest.xml b/src/addons/outlook/manifest.xml
index 08b73910..c19b9cd3 100644
--- a/src/addons/outlook/manifest.xml
+++ b/src/addons/outlook/manifest.xml
@@ -175,15 +175,34 @@
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/addons/outlook/package-lock.json b/src/addons/outlook/package-lock.json
index c3ff2c3b..386af869 100644
--- a/src/addons/outlook/package-lock.json
+++ b/src/addons/outlook/package-lock.json
@@ -10,6 +10,8 @@
"license": "MIT",
"dependencies": {
"core-js": "^3.49.0",
+ "i18next": "26.3.1",
+ "i18next-browser-languagedetector": "8.2.1",
"regenerator-runtime": "^0.14.1"
},
"devDependencies": {
@@ -2111,9 +2113,7 @@
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
"integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
- "dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=6.9.0"
}
@@ -9363,6 +9363,43 @@
"node": ">=10.18"
}
},
+ "node_modules/i18next": {
+ "version": "26.3.1",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.1.tgz",
+ "integrity": "sha512-txQqd5EULsqEh9OJqRH15aCaOuy/nLJyhw5EHCSKLKJE1aBbb3Zve2+uQIxgWhPm1QqUQoWyQBm2kfmmIrzkcQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://www.locize.com/i18next"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.locize.com"
+ }
+ ],
+ "license": "MIT",
+ "peerDependencies": {
+ "typescript": "^5 || ^6"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/i18next-browser-languagedetector": {
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.1.tgz",
+ "integrity": "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ }
+ },
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -15213,7 +15250,7 @@
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
- "dev": true,
+ "devOptional": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
diff --git a/src/addons/outlook/package.json b/src/addons/outlook/package.json
index 95ec552d..279c5ae6 100644
--- a/src/addons/outlook/package.json
+++ b/src/addons/outlook/package.json
@@ -27,6 +27,8 @@
},
"dependencies": {
"core-js": "^3.49.0",
+ "i18next": "26.3.1",
+ "i18next-browser-languagedetector": "8.2.1",
"regenerator-runtime": "^0.14.1"
},
"devDependencies": {
diff --git a/src/addons/outlook/src/commands/commands.js b/src/addons/outlook/src/commands/commands.js
index 09480d33..ae4457dc 100644
--- a/src/addons/outlook/src/commands/commands.js
+++ b/src/addons/outlook/src/commands/commands.js
@@ -5,8 +5,12 @@ const { saveSession, loadSession } = require("../common/session");
const { openTransitDialog } = require("../common/transitDialog");
const { buildMeetingMessage } = require("../common/messageBuilder");
const { applyAppName } = require("../common/helpers");
+const { initI18n, t } = require("../common/i18n");
+
+Office.onReady(async function (info) {
+
+ await initI18n()
-Office.onReady(function (info) {
if (info.host === Office.HostType.Outlook) {
applyAppName();
}
@@ -32,22 +36,22 @@ function insertMeetingLink(event, session) {
return new Promise((resolve, reject) => {
item.body.setSelectedDataAsync(text, { coercionType }, (setResult) => {
if (setResult.status !== Office.AsyncResultStatus.Succeeded) {
- notify(`Erreur d'insertion : ${setResult.error.message}`);
+ notify(t('meeting.error.details', { message: setResult.error.message }));
resolve();
return;
}
if (item.itemType !== Office.MailboxEnums.ItemType.Appointment) {
- notify("Lien de réunion inséré !");
+ notify(t("meeting.link_inserted"));
resolve();
return;
}
item.location.setAsync(url, (locationResult) => {
if (locationResult.status !== Office.AsyncResultStatus.Succeeded) {
- notify(`Erreur de localisation : ${locationResult.error.message}`);
+ notify(t("meeting.error.details", { message: locationResult.error.message }));
} else {
- notify("Lien de réunion inséré !");
+ notify(t("meeting.link_inserted"));
}
resolve();
});
@@ -72,11 +76,11 @@ function connect(event) {
});
},
onTimeout: () => {
- notify("Connexion expirée, veuillez réessayer.");
+ notify(t("meeting.error.auth"));
event.completed();
},
onError: (err) => {
- notify("Une erreur est survenue, veuillez ré-essayer");
+ notify(t("meeting.error.retry"));
event.completed();
},
});
@@ -92,7 +96,7 @@ function connect(event) {
});
})
.catch((err) => {
- notify(`Erreur : ${err.message}`);
+ notify(t("meeting.error.details", { message: err.message }));
event.completed();
});
}
diff --git a/src/addons/outlook/src/common/i18n.js b/src/addons/outlook/src/common/i18n.js
new file mode 100644
index 00000000..ce67be4d
--- /dev/null
+++ b/src/addons/outlook/src/common/i18n.js
@@ -0,0 +1,48 @@
+const { APP_NAME } = require("../common");
+
+const i18nextModule = require("i18next");
+const i18next = i18nextModule.default || i18nextModule;
+
+const fr = require("../locales/fr/translation.json");
+const en = require("../locales/en/translation.json");
+const de = require("../locales/de/translation.json");
+
+async function initI18n() {
+ const lng = typeof Office !== "undefined" ? Office.context.displayLanguage : navigator.language;
+
+ await i18next.init({
+ lng,
+ fallbackLng: "fr",
+ interpolation: { escapeValue: false },
+ resources: {
+ fr: { translation: fr },
+ en: { translation: en },
+ de: { translation: de },
+ },
+ });
+}
+
+function t(key, vars) {
+ return i18next.t(key, vars);
+}
+
+function translateUI() {
+ document.querySelectorAll("[data-i18n]").forEach((el) => {
+ const key = el.getAttribute("data-i18n");
+ el.textContent = t(key, { app_name: APP_NAME });
+ });
+
+ document.querySelectorAll("[data-i18n-attr]").forEach((el) => {
+ const pairs = el.getAttribute("data-i18n-attr").split(",");
+ pairs.forEach((pair) => {
+ const [attr, key] = pair.split(":");
+ el.setAttribute(attr, t(key, { app_name: APP_NAME }));
+ });
+ });
+
+ document.querySelectorAll("[data-i18n-aria]").forEach((el) => {
+ el.setAttribute("aria-label", t(el.getAttribute("data-i18n-aria")));
+ });
+}
+
+module.exports = { initI18n, t, translateUI };
diff --git a/src/addons/outlook/src/common/messageBuilder.js b/src/addons/outlook/src/common/messageBuilder.js
index f29184c2..8a0aab2f 100644
--- a/src/addons/outlook/src/common/messageBuilder.js
+++ b/src/addons/outlook/src/common/messageBuilder.js
@@ -1,4 +1,5 @@
const { APP_NAME } = require("./index");
+const { t } = require("./i18n");
function _formatPin(pin) {
if (!pin) return "";
@@ -33,16 +34,17 @@ function buildMeetingMessage(data, isWeb) {
let textLines = "";
let phoneLines = [];
- phoneLines = phone &&
- pin && [
- "
Ou appelez (audio uniquement)",
- `
(FR) ${phone}`,
- `
Code ${pin}`
- ];
+ const join = t("meeting_message.join", { app_name: APP_NAME });
+ const phoneOnly = t("meeting_message.phone_only");
+ const phoneFr = t("meeting_message.phone_fr", { phone });
+ const pinCode = t("meeting_message.pin_code", { pin });
+
+ if (isWeb) {
+ phoneLines = phone && pin ? [`
${phoneOnly}`, `
${phoneFr}`, `
${pinCode}`] : [];
textLines = [
"
────────────────────────────────────────",
- `
Rejoindre la réunion ${APP_NAME}`,
+ `
${join}`,
`
${url}`,
...phoneLines,
"
────────────────────────────────────────
",
@@ -50,16 +52,11 @@ function buildMeetingMessage(data, isWeb) {
} else {
- phoneLines = phone &&
- pin && [
- "\n\nOu appelez (audio uniquement)",
- `\n(FR) ${phone}`,
- `\nCode ${pin}`
- ];
+ phoneLines = phone && pin ? [`\n\n${phoneOnly}`, `\n${phoneFr}`, `\n${pinCode}`] : [];
textLines = [
"\n\n────────────────────────────────────────",
- `\nRejoindre la réunion ${APP_NAME}`,
+ `\n${join}`,
`\n\n${url}`,
...phoneLines,
"\n────────────────────────────────────────\n",
diff --git a/src/addons/outlook/src/locales/de/translation.json b/src/addons/outlook/src/locales/de/translation.json
new file mode 100644
index 00000000..a86aa9b6
--- /dev/null
+++ b/src/addons/outlook/src/locales/de/translation.json
@@ -0,0 +1,34 @@
+{
+ "app": {
+ "sideload": "Laden Sie das Add-In.",
+ "loading": "Wird geladen..."
+ },
+ "unauth": {
+ "intro": "Fügen Sie Ihren Outlook-Terminen ganz einfach einen {{app_name}}-Besprechungslink hinzu.",
+ "proconnect_btn": "Aanmelden met ProConnect",
+ "proconnect_link": "Wat is ProConnect?",
+ "proconnect_link_title": "Wat is ProConnect? - nieuw venster"
+ },
+ "success": {
+ "close_window": "Falls sich dieses Fenster nicht automatisch schließt, schließen Sie es bitte manuell."
+ },
+ "auth": {
+ "disconnect": "Abmelden"
+ },
+ "meeting": {
+ "link_inserted": "Besprechungslink erfolgreich eingefügt",
+ "generating": "Wird erstellt...",
+ "add_meeting": "{{app_name}}-Besprechung hinzufügen",
+ "error": {
+ "auth": "Ihre Sitzung ist abgelaufen. Bitte versuchen Sie es erneut.",
+ "retry": "Es ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut.",
+ "details": "Fehler: {{message}}"
+ }
+ },
+ "meeting_message": {
+ "join": "An der {{app_name}}-Besprechung teilnehmen",
+ "phone_only": "Oder per Telefon teilnehmen (nur Audio)",
+ "phone_fr": "(FR) {{phone}}",
+ "pin_code": "Code {{pin}}"
+ }
+}
diff --git a/src/addons/outlook/src/locales/en/translation.json b/src/addons/outlook/src/locales/en/translation.json
new file mode 100644
index 00000000..ad49e8d6
--- /dev/null
+++ b/src/addons/outlook/src/locales/en/translation.json
@@ -0,0 +1,34 @@
+{
+ "app": {
+ "sideload": "Please load the add-in.",
+ "loading": "Loading..."
+ },
+ "unauth": {
+ "intro": "Easily add a {{app_name}} meeting link to your Outlook events.",
+ "proconnect_btn": "Sign in with ProConnect",
+ "proconnect_link": "What is ProConnect?",
+ "proconnect_link_title": "What is ProConnect? - new window"
+ },
+ "success": {
+ "close_window": "If this window does not close automatically, please close it manually."
+ },
+ "auth": {
+ "disconnect": "Sign out"
+ },
+ "meeting": {
+ "link_inserted": "Meeting link inserted successfully",
+ "generating": "Generating...",
+ "add_meeting": "Add a {{app_name}} meeting",
+ "error": {
+ "auth": "Your session has expired. Please try again.",
+ "retry": "An error occurred. Please try again.",
+ "details": "Error: {{message}}"
+ }
+ },
+ "meeting_message": {
+ "join": "Join the {{app_name}} meeting",
+ "phone_only": "Or call in (audio only)",
+ "phone_fr": "(FR) {{phone}}",
+ "pin_code": "Code {{pin}}"
+ }
+}
diff --git a/src/addons/outlook/src/locales/fr/translation.json b/src/addons/outlook/src/locales/fr/translation.json
new file mode 100644
index 00000000..b636f922
--- /dev/null
+++ b/src/addons/outlook/src/locales/fr/translation.json
@@ -0,0 +1,34 @@
+{
+ "app": {
+ "sideload": "Veuillez charger le complément.",
+ "loading": "Chargement..."
+ },
+ "unauth": {
+ "intro": "Ajoutez facilement un lien de réunion {{app_name}} à vos événements Outlook.",
+ "proconnect_btn": "S'identifier avec ProConnect",
+ "proconnect_link": "Qu'est-ce que ProConnect ?",
+ "proconnect_link_title": "Qu'est-ce que ProConnect ? - nouvelle fenêtre"
+ },
+ "success": {
+ "close_window": "Si cette fenêtre ne se ferme pas toute seule, veuillez la fermer manuellement."
+ },
+ "auth": {
+ "disconnect": "Se déconnecter"
+ },
+ "meeting": {
+ "link_inserted": "Lien de réunion inséré avec succès",
+ "generating": "Génération...",
+ "add_meeting": "Ajouter une réunion {{app_name}}",
+ "error": {
+ "auth": "Connexion expirée, veuillez réessayer.",
+ "retry": "Une erreur est survenue, veuillez ré-essayer",
+ "details": "Erreur : {{message}}"
+ }
+ },
+ "meeting_message": {
+ "join": "Rejoindre la réunion {{app_name}}",
+ "phone_only": "Ou appelez (audio uniquement)",
+ "phone_fr": "(FR) {{phone}}",
+ "pin_code": "Code {{pin}}"
+ }
+}
diff --git a/src/addons/outlook/src/success/success.html b/src/addons/outlook/src/success/success.html
index d1603e88..09bbd3eb 100644
--- a/src/addons/outlook/src/success/success.html
+++ b/src/addons/outlook/src/success/success.html
@@ -9,10 +9,10 @@
- Veuillez charger le complément.
+
-
- Si cette fenêtre ne se ferme pas toute seule, veuillez la fermer manuellement.
-
+