Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/locales/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@
"timeslider.month.october": "أكتوبر",
"timeslider.month.november": "نوفمبر",
"timeslider.month.december": "ديسمبر",
"timeslider.unnamedauthors": "بدون اسم {{num}} {[plural(num) واحد: كاتب، آخر: مؤلف]}",
"timeslider.unnamedauthors": "بدون اسم {{num}} {[plural(num) one: كاتب, other: مؤلف ]}",
"pad.savedrevs.marked": "هذا التنقيح محدد الآن كمراجعة محفوظة",
"pad.savedrevs.timeslider": "يمكنك عرض المراجعات المحفوظة بزيارة متصفح التاريخ",
"pad.userlist.entername": "أدخل اسمك",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/diq.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@
"timeslider.month.october": "Tışrino Verên",
"timeslider.month.november": "Tışrino Peyên",
"timeslider.month.december": "Kanun",
"timeslider.unnamedauthors": "{{num}} unnamed {[plural(num) zu: nuştoğ, zewbi: nustoği ]}",
"timeslider.unnamedauthors": "{{num}} unnamed {[plural(num) one: nuştoğ, other: nustoği ]}",
"pad.savedrevs.marked": "Eno vurriyayış henda qeyd bıyaye yew vurriyayış deyne nışan bıyo",
"pad.savedrevs.timeslider": "Xızberê zemani ziyer kerdış ra şıma şenê revizyonanê qeyd bıyayan bıvinê",
"pad.userlist.entername": "Namey xo cıkewe",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/ff.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
"timeslider.month.october": "Yarkomaa",
"timeslider.month.november": "Jolal",
"timeslider.month.december": "Bowte",
"timeslider.unnamedauthors": "{{num}} innitaaka {[plural(num) goo: ballifo, goɗɗo: wallifɓe]}",
"timeslider.unnamedauthors": "{{num}} innitaaka {[plural(num) one: ballifo, other: wallifɓe ]}",
"pad.savedrevs.marked": "Ndee yamre maantaama jooni ko baylital danndangal",
"pad.savedrevs.timeslider": "Aɗa waawi yiyde baylitte danndaaɗe so yillaade daasorde tuma ndee",
"pad.userlist.entername": " Naatnu innde maa",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/hr.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
"timeslider.month.october": "listopada",
"timeslider.month.november": "studenoga",
"timeslider.month.december": "prosinca",
"timeslider.unnamedauthors": "{{num}} {[plural(num) one: neimenovani autor, plural(num) two: neimenovana autora, plural(num) other: neimenovanih autora ]}",
"timeslider.unnamedauthors": "{{num}} {[plural(num) one: neimenovani autor, two: neimenovana autora, other: neimenovanih autora ]}",
"pad.savedrevs.marked": "Ova inačica označena je sada kao spremljena inačica",
"pad.savedrevs.timeslider": "Možete vidjeti spremljene inačice rabeći vremensku lentu (timeslider)",
"pad.userlist.entername": "Unesite Vaše suradničko ime",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/hu.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
"timeslider.month.october": "október",
"timeslider.month.november": "november",
"timeslider.month.december": "december",
"timeslider.unnamedauthors": "{{num}} névtelen {[plural(num), one: szerző, other: szerző]}",
"timeslider.unnamedauthors": "{{num}} névtelen {[plural(num) one: szerző, other: szerző ]}",
"pad.savedrevs.marked": "Ez a revízió mostantól mentettként jelölve",
"pad.savedrevs.timeslider": "A mentett revíziókat az időcsúszkán tudod megnézni",
"pad.userlist.entername": "Add meg a nevedet",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@
"pad.savedrevs.timeslider": "Puoi vedere le versioni salvate visitando la cronologia",
"pad.userlist.entername": "Inserisci il tuo nome",
"pad.userlist.unnamed": "senza nome",
"pad.userlist.onlineCount": "{[ plurale(count) uno: {{count}} utente connesso, altro: {{count}} utenti connessi ]}",
"pad.userlist.onlineCount": "{[ plural(count) one: {{count}} utente connesso, other: {{count}} utenti connessi ]}",
"pad.editbar.clearcolors": "Eliminare i colori degli autori sull'intero documento? Questa azione non può essere annullata",
"pad.impexp.importbutton": "Importa ora",
"pad.impexp.importing": "Importazione in corso...",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/mnw.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"timeslider.month.october": "\nအံက်တဝ်ပါ",
"timeslider.month.november": "\nနဝ်ဝေမ်ပါ",
"timeslider.month.december": "ဒဳဇြေန်ပါ",
"timeslider.unnamedauthors": "{{num}} ဟွံကဵုယၟု {[ဂမၠိုၚ်(num) မွဲ: ကဝိ, တၞဟ်: ကဝိဂမၠိုၚ် ]}",
"timeslider.unnamedauthors": "{{num}} ဟွံကဵုယၟု {[plural(num) one: ကဝိ, other: ကဝိဂမၠိုၚ် ]}",
"pad.userlist.entername": "စုတ် ယၟုညးလွပ်",
"pad.userlist.unnamed": "ဟွံကဵုလဝ်ယၟု",
"pad.impexp.importbutton": " မပၠောပ်စုတ် လၟုဟ်",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/my.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@
"timeslider.month.october": "အောက်တိုဘာ",
"timeslider.month.november": "နို​ဝင်​ဘာ​",
"timeslider.month.december": "ဒီဇင်ဘာ",
"timeslider.unnamedauthors": "{{num}} အမည်မဖော်လိုသူ {[အများကိန်း (num) one: author၊ အခြား: author]}",
"timeslider.unnamedauthors": "{{num}} အမည်မဖော်လိုသူ {[plural(num) one: author, other: author ]}",
"pad.savedrevs.marked": "ယခုပြန်လည်တည်းဖြတ်မှုအားသိမ်းဆည်းထားသောတည်းဖြတ်မှုတစ်ခုအဖြစ်အမှတ်အသားပြုထားသည်",
"pad.savedrevs.timeslider": "timeslider ကိုသွားခြင်းဖြင့်သိမ်းဆည်းထားသောပြန်လည်တည်းဖြတ်ချက်များကိုသင်မြင်နိုင်သည်",
"pad.userlist.entername": "မင်းနာမည်ထည့်ပါ",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/ps.json
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@
"timeslider.month.october": "اکتوبر",
"timeslider.month.november": "نومبر",
"timeslider.month.december": "ډېسمبر",
"timeslider.unnamedauthors": "{{num}} بې نومه {[ډېرگړي(num) يو: ليکوال، نور: ليکوالان ]}",
"timeslider.unnamedauthors": "{{num}} بې نومه {[plural(num) one: ليکوال, other: ليکوالان ]}",
"pad.savedrevs.marked": "اوس دا بياليدنه د يوې خوندي شوې بياليدنې په توگه په نښه شوه",
"pad.userlist.entername": "نوم مو ورکړئ",
"pad.userlist.unnamed": "بې نومه",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/ro.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
"timeslider.month.october": "octombrie",
"timeslider.month.november": "noiembrie",
"timeslider.month.december": "decembrie",
"timeslider.unnamedauthors": "{{num}} anonim {[plural (num) unul: autor, altul: autori ]}",
"timeslider.unnamedauthors": "{{num}} anonim {[plural(num) one: autor, other: autori ]}",
"pad.savedrevs.marked": "Această revizie este marcată acum ca o revizuire salvată",
"pad.savedrevs.timeslider": "Puteți vedea reviziile salvate accesând cursorul de timp",
"pad.userlist.entername": "Introduceți numele dumneavoastră",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/sh-latn.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
"timeslider.month.october": "oktobra",
"timeslider.month.november": "novembra",
"timeslider.month.december": "decembra",
"timeslider.unnamedauthors": "{{num}} {[plural(num) one: neimenovani autor, plural(num) two: neimenovana autora, plural(num) other: neimenovanih autora ]}",
"timeslider.unnamedauthors": "{{num}} {[plural(num) one: neimenovani autor, two: neimenovana autora, other: neimenovanih autora ]}",
"pad.savedrevs.marked": "Ova inačica označena je sada kao spremljena",
"pad.savedrevs.timeslider": "Možete pogledati spremljene inačice rabeći vremesledni klizač",
"pad.userlist.entername": "Upišite svoje ime",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/shn.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
"timeslider.month.october": "ဢွၵ်ႇထူဝ်ႇပႃႇ",
"timeslider.month.november": "ၼူဝ်ႇဝႅမ်ႇပႃႇ",
"timeslider.month.december": "တီႇသႅမ်ႇပႃႇ",
"timeslider.unnamedauthors": "{{num}} ဢမ်ႇသႂ်ႇၸိုဝ်ႈ {[plural(num) ၼိုင်ႈ: ၽူႈတႅမ်ႈလိၵ်ႈ, တၢင်ႇၸိူဝ်း: ၽူႈတႅမ်ႈလိၵ်ႈၶဝ် ]}",
"timeslider.unnamedauthors": "{{num}} ဢမ်ႇသႂ်ႇၸိုဝ်ႈ {[plural(num) one: ၽူႈတႅမ်ႈလိၵ်ႈ, other: ၽူႈတႅမ်ႈလိၵ်ႈၶဝ် ]}",
"pad.savedrevs.marked": "ဢၼ်မႄးဝႆႉၼႆႉ ယၢမ်းလဵဝ် ၶိုၼ်းမႄး ၵဵပ်းသိမ်းဝႆႉ ၸိူင်ႉၼင်ႇဢၼ်ၼိုင်ႈ",
"pad.savedrevs.timeslider": "ၸဝ်ႈၵဝ်ႇတေတူၺ်းလႆႈ ဢၼ်ၶိုၼ်းမႄးသိမ်းဝႆႉၼၼ်ႉယူႇ ပေႃးၶဝ်ႈတူၺ်းတီႈ ၶၢဝ်းယၢမ်းထေႃပူၼ်ႉ",
"pad.userlist.entername": "ပေႃႇသႂ်ႇပၼ် ၸိုဝ်ႈၽူႈၸႂ်ႉတိုဝ်း ၸဝ်ႈၵဝ်ႇ",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/sl.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@
"timeslider.month.october": "oktobra",
"timeslider.month.november": "novembra",
"timeslider.month.december": "decembra",
"timeslider.unnamedauthors": "{{num}} {[plural(num) one: neimenovan avtor, plural(num) two: neimenovana avtorja, plural(num) few: neimenovani avtorji, other: neimenovanih avtorjev ]}",
"timeslider.unnamedauthors": "{{num}} {[plural(num) one: neimenovan avtor, two: neimenovana avtorja, few: neimenovani avtorji, other: neimenovanih avtorjev ]}",
"pad.savedrevs.marked": "Ta redakcija je zdaj označena kot shranjena redakcija",
"pad.savedrevs.timeslider": "Shranjene redakcije si lahko ogledate z odprtjem časovnega traku",
"pad.userlist.entername": "Vnesite svoje ime",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/sq.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
"timeslider.month.october": "Tetor",
"timeslider.month.november": "Nëntor",
"timeslider.month.december": "Dhjetor",
"timeslider.unnamedauthors": "{{num}} i paemër {[plural(num) një: autor, tjetër:{{num}} autorë ]}",
"timeslider.unnamedauthors": "{{num}} i paemër {[plural(num) one: autor, other: autorë ]}",
"pad.savedrevs.marked": "Ky rishikim tani është shënuar si rishikim i ruajtur",
"pad.savedrevs.timeslider": "Rishikimet e ruajtura mund t’i shihni duke vizituar rrjedhën kohore",
"pad.userlist.entername": "Jepni emrin tuaj",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/sw.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
"timeslider.month.october": "Oktoba",
"timeslider.month.november": "Novemba",
"timeslider.month.december": "Desemba",
"timeslider.unnamedauthors": "{{num}} haijatajwa jina {[wingi (num) moja: mwandishi, mwingine: waandishi]}",
"timeslider.unnamedauthors": "{{num}} haijatajwa jina {[plural(num) one: mwandishi, other: waandishi ]}",
"pad.savedrevs.marked": "Marekebisho haya sasa yamewekwa alama kama marekebisho yaliyohifadhiwa",
"pad.savedrevs.timeslider": "Unaweza kuona marekebisho yaliyohifadhiwa kwa kutembelea mpangilio wa nyakati",
"pad.userlist.entername": "Ingiza jina lako",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
"timeslider.month.october": "Tháng Mười",
"timeslider.month.november": "Tháng Mười Một",
"timeslider.month.december": "Tháng Mười Hai",
"timeslider.unnamedauthors": "Không tên {{in a}} {[plural(num) một: tác giả, khác: tác giả]}",
"timeslider.unnamedauthors": "Không tên {{in a}} {[plural(num) one: tác giả, other: tác giả ]}",
"pad.savedrevs.marked": "Phiên bản này đã được đánh dấu là một phiên bản đã lưu",
"pad.userlist.entername": "Nhập tên của bạn",
"pad.userlist.unnamed": "Không tên",
Expand Down
101 changes: 101 additions & 0 deletions src/tests/backend-new/specs/locale-files.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
'use strict';

import {readFileSync, readdirSync} from 'fs';
import {join} from 'path';
import {describe, it, expect} from 'vitest';

const repoRoot = join(__dirname, '..', '..', '..', '..');
const localesDir = join(repoRoot, 'src', 'locales');
const localeFiles = readdirSync(localesDir)
.filter((f) => f.endsWith('.json'))
.map((f) => join(localesDir, f));

const macroCandidateRe = /\{\[[^]*?]}/g;

const parseMacro = (candidate: string): {macroName: string, options: string} | null => {
if (!candidate.startsWith('{[') || !candidate.endsWith(']}')) return null;
const body = candidate.slice(2, -2).trim();
const openParen = body.indexOf('(');
const closeParen = body.indexOf(')', openParen + 1);
if (openParen <= 0 || closeParen <= openParen + 1) return null;
const macroName = body.slice(0, openParen).trim();
const variableName = body.slice(openParen + 1, closeParen).trim();
if (!/^[a-zA-Z]+$/.test(macroName) || !/^[a-zA-Z]+$/.test(variableName)) return null;
return {macroName, options: body.slice(closeParen + 1).trim()};
};

const parsePluralOptionNames = (options: string): string[] | null => {
if (options === '') return [];
const names: string[] = [];
let i = 0;
while (i < options.length) {
while (i < options.length && /\s/.test(options[i])) i++;
const nameStart = i;
while (i < options.length && /[a-zA-Z]/.test(options[i])) i++;
if (nameStart === i || options[i] !== ':') return null;
names.push(options.slice(nameStart, i));
i++;
while (i < options.length) {
if (options[i] === ',') {
i++;
break;
}
i++;
}
}
return names;
};
const allowedMacros = new Set(['plural']);
const allowedPluralOptions = new Set(['zero', 'one', 'two', 'few', 'many', 'other']);

describe('locale files', () => {
it('current locale corpus contains no unsupported macros', () => {
const failures: string[] = [];
for (const file of localeFiles) {
const rel = file.replace(repoRoot + '/', '');
const parsed = JSON.parse(readFileSync(file, 'utf8')) as Record<string, string>;
for (const [key, value] of Object.entries(parsed)) {
if (key === '@metadata') continue;
for (const candidate of value.match(macroCandidateRe) ?? []) {
const macro = parseMacro(candidate);
if (macro == null) {
failures.push(`${rel}:${key}:malformed:${candidate}`);
continue;
}
const {macroName, options} = macro;
if (!allowedMacros.has(macroName)) failures.push(`${rel}:${key}:${macroName}`);
if (macroName !== 'plural') continue;
Comment thread
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
const optionNames = parsePluralOptionNames(options);
if (optionNames == null) {
failures.push(`${rel}:${key}:malformed:${candidate}`);
continue;
}
for (const name of optionNames) {
if (!allowedPluralOptions.has(name)) failures.push(`${rel}:${key}:${name}`);
}
}
}
}
expect(failures).toEqual([]);
});

for (const file of localeFiles) {
const rel = file.replace(repoRoot + '/', '');

it(`${rel} contains a JSON object of string translations`, () => {
const parsed = JSON.parse(readFileSync(file, 'utf8'));
expect(parsed, `${rel} must contain a JSON object`).toBeTruthy();
expect(Array.isArray(parsed), `${rel} must not contain a JSON array`).toBe(false);
expect(typeof parsed, `${rel} must contain a JSON object`).toBe('object');
for (const [key, value] of Object.entries(parsed as Record<string, unknown>)) {
if (key === '@metadata') {
expect(value != null && typeof value === 'object' && !Array.isArray(value),
`${rel} key @metadata must map to an object`).toBe(true);
continue;
}
expect(typeof value, `${rel} key ${key} must map to a string`).toBe('string');
}
});

}
});
Loading