From b98c02cbf403f898853a086450891e19155e756f Mon Sep 17 00:00:00 2001 From: Parvin Mehrabani Date: Fri, 7 Aug 2026 12:24:58 +0300 Subject: [PATCH] feat(i18n): add Russian, Chinese, Portuguese, Italian, Japanese, Turkish, and Korean translations --- src/i18n/it_IT.ts | 13 ++++++++++ src/i18n/ja_JP.ts | 13 ++++++++++ src/i18n/ko_KR.ts | 13 ++++++++++ src/i18n/language.test.ts | 47 +++++++++++++++++++++++++++++++------ src/i18n/language.ts | 14 +++++++++++ src/i18n/pt_BR.ts | 13 ++++++++++ src/i18n/ru_RU.ts | 13 ++++++++++ src/i18n/tr_TR.ts | 13 ++++++++++ src/i18n/zh_CN.ts | 13 ++++++++++ src/packages/hint/option.ts | 3 ++- src/packages/tour/option.ts | 3 ++- 11 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 src/i18n/it_IT.ts create mode 100644 src/i18n/ja_JP.ts create mode 100644 src/i18n/ko_KR.ts create mode 100644 src/i18n/pt_BR.ts create mode 100644 src/i18n/ru_RU.ts create mode 100644 src/i18n/tr_TR.ts create mode 100644 src/i18n/zh_CN.ts diff --git a/src/i18n/it_IT.ts b/src/i18n/it_IT.ts new file mode 100644 index 000000000..18b9a380a --- /dev/null +++ b/src/i18n/it_IT.ts @@ -0,0 +1,13 @@ +export default { + buttons: { + next: "Avanti", + prev: "Indietro", + skip: "Salta", + done: "Fine", + gotIt: "Capito", + }, + messages: { + dontShowAgainLabel: "Non mostrare più", + stepNumbersOfLabel: "di", + }, +}; diff --git a/src/i18n/ja_JP.ts b/src/i18n/ja_JP.ts new file mode 100644 index 000000000..51a15c467 --- /dev/null +++ b/src/i18n/ja_JP.ts @@ -0,0 +1,13 @@ +export default { + buttons: { + next: "次へ", + prev: "戻る", + skip: "スキップ", + done: "完了", + gotIt: "了解", + }, + messages: { + dontShowAgainLabel: "今後表示しない", + stepNumbersOfLabel: "/", + }, +}; diff --git a/src/i18n/ko_KR.ts b/src/i18n/ko_KR.ts new file mode 100644 index 000000000..b6f2238a2 --- /dev/null +++ b/src/i18n/ko_KR.ts @@ -0,0 +1,13 @@ +export default { + buttons: { + next: "다음", + prev: "이전", + skip: "건너뛰기", + done: "완료", + gotIt: "확인", + }, + messages: { + dontShowAgainLabel: "다시 보지 않기", + stepNumbersOfLabel: "/", + }, +}; diff --git a/src/i18n/language.test.ts b/src/i18n/language.test.ts index f3dd299ce..833d448ec 100644 --- a/src/i18n/language.test.ts +++ b/src/i18n/language.test.ts @@ -46,7 +46,7 @@ describe("Translator", () => { }); it("should fallback to en_US for unsupported languages", () => { - createMockNavigator("zh-CN"); + createMockNavigator("sv-SE"); const translator = new Translator(); expect(translator.translate("buttons.next")).toBe("Next"); }); @@ -74,15 +74,48 @@ describe("Translator", () => { it("should work with all supported languages", () => { const translator = new Translator(); - (["en_US", "es_ES", "fr_FR", "de_DE", "fa_IR"] as LanguageCode[]).forEach( - (code) => { - translator.setLanguage(code); - expect(typeof translator.translate("buttons.next")).toBe("string"); - } - ); + getAvailableLanguages().forEach((code) => { + translator.setLanguage(code); + expect(typeof translator.translate("buttons.next")).toBe("string"); + }); }); }); + describe("newly added languages", () => { + it.each([ + ["ru_RU", "Далее"], + ["zh_CN", "下一步"], + ["pt_BR", "Próximo"], + ["it_IT", "Avanti"], + ["ja_JP", "次へ"], + ["tr_TR", "İleri"], + ["ko_KR", "다음"], + ])("translates buttons.next for %s", (code, expected) => { + const translator = new Translator(code as LanguageCode); + expect(translator.translate("buttons.next")).toBe(expected); + }); + + it.each(["ru_RU", "zh_CN", "pt_BR", "it_IT", "ja_JP", "tr_TR", "ko_KR"])( + "has non-empty translations for every key in %s", + (code) => { + const translator = new Translator(code as LanguageCode); + [ + "buttons.next", + "buttons.prev", + "buttons.skip", + "buttons.done", + "buttons.gotIt", + "messages.dontShowAgainLabel", + "messages.stepNumbersOfLabel", + ].forEach((key) => { + const translated = translator.translate(key); + expect(translated).not.toBe(key); + expect(translated.length).toBeGreaterThan(0); + }); + } + ); + }); + describe("translate", () => { let translator: Translator; diff --git a/src/i18n/language.ts b/src/i18n/language.ts index 5eed6a2e2..67a429caa 100644 --- a/src/i18n/language.ts +++ b/src/i18n/language.ts @@ -4,6 +4,13 @@ import deDE from "./de_DE"; import esES from "./es_ES"; import frFR from "./fr_FR"; import ar_SA from "./ar_SA"; +import ru_RU from "./ru_RU"; +import zh_CN from "./zh_CN"; +import pt_BR from "./pt_BR"; +import it_IT from "./it_IT"; +import ja_JP from "./ja_JP"; +import tr_TR from "./tr_TR"; +import ko_KR from "./ko_KR"; const languages = { en_US: enUS, @@ -12,6 +19,13 @@ const languages = { es_ES: esES, fr_FR: frFR, ar_SA: ar_SA, + ru_RU: ru_RU, + zh_CN: zh_CN, + pt_BR: pt_BR, + it_IT: it_IT, + ja_JP: ja_JP, + tr_TR: tr_TR, + ko_KR: ko_KR, } as const; export type LanguageCode = keyof typeof languages; diff --git a/src/i18n/pt_BR.ts b/src/i18n/pt_BR.ts new file mode 100644 index 000000000..f3b99ee46 --- /dev/null +++ b/src/i18n/pt_BR.ts @@ -0,0 +1,13 @@ +export default { + buttons: { + next: "Próximo", + prev: "Voltar", + skip: "Pular", + done: "Concluído", + gotIt: "Entendi", + }, + messages: { + dontShowAgainLabel: "Não mostrar novamente", + stepNumbersOfLabel: "de", + }, +}; diff --git a/src/i18n/ru_RU.ts b/src/i18n/ru_RU.ts new file mode 100644 index 000000000..47ff8b6fa --- /dev/null +++ b/src/i18n/ru_RU.ts @@ -0,0 +1,13 @@ +export default { + buttons: { + next: "Далее", + prev: "Назад", + skip: "Пропустить", + done: "Готово", + gotIt: "Ясно", + }, + messages: { + dontShowAgainLabel: "Больше не показывать", + stepNumbersOfLabel: "из", + }, +}; diff --git a/src/i18n/tr_TR.ts b/src/i18n/tr_TR.ts new file mode 100644 index 000000000..ad8275911 --- /dev/null +++ b/src/i18n/tr_TR.ts @@ -0,0 +1,13 @@ +export default { + buttons: { + next: "İleri", + prev: "Geri", + skip: "Atla", + done: "Bitti", + gotIt: "Anladım", + }, + messages: { + dontShowAgainLabel: "Bir daha gösterme", + stepNumbersOfLabel: "/", + }, +}; diff --git a/src/i18n/zh_CN.ts b/src/i18n/zh_CN.ts new file mode 100644 index 000000000..62c3da531 --- /dev/null +++ b/src/i18n/zh_CN.ts @@ -0,0 +1,13 @@ +export default { + buttons: { + next: "下一步", + prev: "上一步", + skip: "跳过", + done: "完成", + gotIt: "知道了", + }, + messages: { + dontShowAgainLabel: "不再显示", + stepNumbersOfLabel: "/", + }, +}; diff --git a/src/packages/hint/option.ts b/src/packages/hint/option.ts index e2c0378a9..d395537fc 100644 --- a/src/packages/hint/option.ts +++ b/src/packages/hint/option.ts @@ -33,7 +33,8 @@ export interface HintOptions { tooltipRenderAsHtml?: boolean; /* Optional property to set the language of the hint. Can be a Language object for custom languages or a language code string for built-in languages. - Built-in language codes: "en_US", "es_ES", "fr_FR", "de_DE", "fa_IR" + Built-in language codes: "en_US", "es_ES", "fr_FR", "de_DE", "fa_IR", + "ar_SA", "ru_RU", "zh_CN", "pt_BR", "it_IT", "ja_JP", "tr_TR", "ko_KR" Defaults to the user's browser language if not provided. */ language?: LanguageCode; } diff --git a/src/packages/tour/option.ts b/src/packages/tour/option.ts index 54ad1bfbf..565f23b5a 100644 --- a/src/packages/tour/option.ts +++ b/src/packages/tour/option.ts @@ -77,7 +77,8 @@ export interface TourOptions { tooltipRenderAsHtml?: boolean; /* Optional property to set the language of the tour. Can be a Language object for custom languages or a language code string for built-in languages. - Built-in language codes: "en_US", "es_ES", "fr_FR", "de_DE", "fa_IR" + Built-in language codes: "en_US", "es_ES", "fr_FR", "de_DE", "fa_IR", + "ar_SA", "ru_RU", "zh_CN", "pt_BR", "it_IT", "ja_JP", "tr_TR", "ko_KR" Defaults to the user's browser language if not provided. */ language?: LanguageCode; }