Skip to content

Commit 3908245

Browse files
committed
frontend/i18n: adding french, italian and russian
1 parent f376403 commit 3908245

18 files changed

+7746
-4
lines changed

src/packages/frontend/app/localize.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ function loadAntdLocale(locale: Locale): Promise<AntdLocale> {
140140
return import("antd/locale/zh_CN");
141141
case "es":
142142
return import("antd/locale/es_ES");
143+
case "ru":
144+
return import("antd/locale/ru_RU");
145+
case "fr":
146+
return import("antd/locale/fr_FR");
147+
case "it":
148+
return import("antd/locale/it_IT");
143149
default:
144150
unreachable(locale);
145151
throw new Error(`Unknown locale '${locale}.`);

src/packages/frontend/i18n/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,31 @@ We discussed this internally on 2024-08-19 and came to the conclusion that we sh
8282
- Example: translating the "Run" button in Jupyter to German or Russian, which both have more or less the meaning of "running in the street", is extremely awkward. It's also a well recognizable element, which users are used to, even without knowing what it really means. Same holds for "Kernel", which is even in English a pretty weird choice. Therefore, we do not translate elements like the "Run" button or "Kernel" for Jupyter Kernels. A "Run" menu however, in general, could be translated (e.g. in German it is called "Ausführen").
8383
- However, what we should translate (or add) are hover text explanations. So, in the case of the "Run" button, there should be a tooltip, which explains in the current language, what this button really does.
8484

85+
## SimpleLocalize configuration
86+
87+
This is about auto-translations, in "Settings → Auto-translation":
88+
89+
- To start: when you add a new language, set its full code, e.g. "fr_FR", name "French" and language "French". Translation provider: OpenAI.
90+
- You need the API key, it's in Integrations → REST API. See notes above.
91+
- In the Auto-translate configuration, OpenAI → Configure:
92+
93+
- API key: a separate one to track usage, it's fine to restrict its capabilities to list and use models.
94+
- GPT-4o
95+
- System prompt: here, the key point is to give some context and to instruct it to retain those ICU messages. That's what I came up with after a few tests and iterations:
96+
97+
Translation of strings in the user-interface of the online platform "CoCalc".
98+
99+
Stay close to the original meaning of the source text and match the length and style. In particular, short labels of commands must stay short.
100+
101+
If a label ends with "...", keep those dots in the translation.
102+
103+
Retain the syntax of ICU formatted messages. They could contain variables like `some text {variable} more text` or conditionals like `{variable, select, option1 {...} other {...}}`.
104+
105+
- add description as context: Yes. (I assume this uses the "code description")
106+
107+
- Exclusion dialect: ICU messages
108+
- Excluded words or phrases: CoCalc
109+
85110
## Examples
86111

87112
Here are examples of how to use this:
@@ -134,6 +159,7 @@ other {}
134159
- Ref: ICU Messages: https://unicode-org.github.io/icu/userguide/format_parse/messages/
135160
- **okText**: That's a simple string, where the English variant is defined right here. Note, that the ID of the OK text and the title are very similar.
136161
- **cancelText**: That references a common message, which is used in many places. It's the "Cancel" text on the button. The `labels` object comes from `import { labels } from "@cocalc/frontend/i18n"`.
162+
- There is also a tiny component as an example, for how to translate a bit via a component: `i18n/components.tsx``<CancelText />`
137163

138164
## Menu entries
139165

@@ -163,3 +189,5 @@ build_on_save: {
163189
label: ({ intl }) => intl.formatMessage({ id: "...", defaultMessage: "..."}, { ...values })
164190
}
165191
```
192+
193+
Many of those messages are actually defined in `i18n/common.ts`. There are groups of messages, e.g. `jupyter.commands`. Messages are only extracted from `*.tsx` and some `*.ts` files – check the code of `i18n/bin/extract.sh` to see what's going on. This file is accompanied by `i18n.test.ts`, which checks the prefixes of all IDs!
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
LANGS="de_DE zh_CN es_ES"
1+
LANGS="de_DE zh_CN es_ES fr_FR ru_RU it_IT"

src/packages/frontend/i18n/de_DE.compiled.json

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,12 +959,30 @@
959959
"value": "Englisch"
960960
}
961961
],
962+
"i18n.localization.lang.french": [
963+
{
964+
"type": 0,
965+
"value": "Französisch"
966+
}
967+
],
962968
"i18n.localization.lang.german": [
963969
{
964970
"type": 0,
965971
"value": "Deutsch"
966972
}
967973
],
974+
"i18n.localization.lang.italian": [
975+
{
976+
"type": 0,
977+
"value": "Italienisch"
978+
}
979+
],
980+
"i18n.localization.lang.russian": [
981+
{
982+
"type": 0,
983+
"value": "Russisch"
984+
}
985+
],
968986
"i18n.localization.lang.spanish": [
969987
{
970988
"type": 0,
@@ -2074,7 +2092,7 @@
20742092
"children": [
20752093
{
20762094
"type": 0,
2077-
"value": "TimeTravel-Historie"
2095+
"value": "ZeitReise-Historie"
20782096
}
20792097
],
20802098
"type": 8,

src/packages/frontend/i18n/de_DE.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@
8989
"frame_editors.frame_tree.title_bar.minimize": "Alle Fenster anzeigen",
9090
"i18n.localization.lang.chinese": "Chinesisch",
9191
"i18n.localization.lang.english": "Englisch",
92+
"i18n.localization.lang.french": "Französisch",
9293
"i18n.localization.lang.german": "Deutsch",
94+
"i18n.localization.lang.italian": "Italienisch",
95+
"i18n.localization.lang.russian": "Russisch",
9396
"i18n.localization.lang.spanish": "Spanisch",
9497
"jupyter.commands.cell_toolbar_none": "Keine Zellen-Werkzeugleiste",
9598
"jupyter.commands.cell_toolbar_none_menu": "Keine",
@@ -260,7 +263,7 @@
260263
"menu.generic.run.label": "Ausführen",
261264
"menu.generic.split.button": "Teilen",
262265
"menu.generic.view.label": "Ansicht",
263-
"new.file-type-page.header.description": "Was möchten Sie erstellen? Dokumente können gleichzeitig von mehreren Personen bearbeitet werden, führen eine vollständige <A>TimeTravel-Historie</A> der Änderungen und unterstützen die Auswertung von Code.",
266+
"new.file-type-page.header.description": "Was möchten Sie erstellen? Dokumente können gleichzeitig von mehreren Personen bearbeitet werden, führen eine vollständige <A>ZeitReise-Historie</A> der Änderungen und unterstützen die Auswertung von Code.",
264267
"new.file-type-page.header.intro": "Benennen Sie Ihre Datei, Ihren Ordner oder fügen Sie einen Link ein. Beenden Sie den Namen mit /, um einen Ordner zu erstellen.",
265268
"new.file-type-selector.folder.tooltip": "Erstellen Sie einen Ordner (Unterverzeichnis), in dem Sie Ihre Dateien speichern und organisieren können. CoCalc bietet ein voll ausgestattetes Dateisystem. Sie können auch einen Pfad im obigen Eingabefeld eingeben, der mit einem Schrägstrich / endet, und die Eingabetaste drücken.",
266269
"new.file-type-selector.latex.tooltip": "Erstellen Sie ein technisches Papier in professioneller Qualität, das anspruchsvolle mathematische Formeln enthält und Python-, R- und Sage-Code ausführen kann.",

src/packages/frontend/i18n/es_ES.compiled.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,12 +959,30 @@
959959
"value": "Inglés"
960960
}
961961
],
962+
"i18n.localization.lang.french": [
963+
{
964+
"type": 0,
965+
"value": "Francés"
966+
}
967+
],
962968
"i18n.localization.lang.german": [
963969
{
964970
"type": 0,
965971
"value": "Alemán"
966972
}
967973
],
974+
"i18n.localization.lang.italian": [
975+
{
976+
"type": 0,
977+
"value": "Italiano"
978+
}
979+
],
980+
"i18n.localization.lang.russian": [
981+
{
982+
"type": 0,
983+
"value": "Ruso"
984+
}
985+
],
968986
"i18n.localization.lang.spanish": [
969987
{
970988
"type": 0,

src/packages/frontend/i18n/es_ES.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@
8989
"frame_editors.frame_tree.title_bar.minimize": "Mostrar todos los marcos",
9090
"i18n.localization.lang.chinese": "Chino",
9191
"i18n.localization.lang.english": "Inglés",
92+
"i18n.localization.lang.french": "Francés",
9293
"i18n.localization.lang.german": "Alemán",
94+
"i18n.localization.lang.italian": "Italiano",
95+
"i18n.localization.lang.russian": "Ruso",
9396
"i18n.localization.lang.spanish": "Español",
9497
"jupyter.commands.cell_toolbar_none": "Sin barra de herramientas de celda",
9598
"jupyter.commands.cell_toolbar_none_menu": "Ninguno",

src/packages/frontend/i18n/extracted.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,9 +284,18 @@
284284
"i18n.localization.lang.english": {
285285
"defaultMessage": "English"
286286
},
287+
"i18n.localization.lang.french": {
288+
"defaultMessage": "French"
289+
},
287290
"i18n.localization.lang.german": {
288291
"defaultMessage": "German"
289292
},
293+
"i18n.localization.lang.italian": {
294+
"defaultMessage": "Italian"
295+
},
296+
"i18n.localization.lang.russian": {
297+
"defaultMessage": "Russian"
298+
},
290299
"i18n.localization.lang.spanish": {
291300
"defaultMessage": "Spanish"
292301
},

0 commit comments

Comments
 (0)