Skip to content

Commit b2bfd5c

Browse files
authored
Merge pull request #806 from smapiot/feature/fallback-language
Add "fallbackLanguage" to piral-translate
2 parents 38f052b + 9dbe975 commit b2bfd5c

File tree

4 files changed

+35
-6
lines changed

4 files changed

+35
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## 1.10.1 (tbd)
44

55
- Improved trusted publishing
6+
- Added `fallbackLanguage` in `piral-translate`
67

78
## 1.10.0 (February 24, 2026)
89

src/plugins/piral-translate/src/create.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ export interface LocaleConfig {
3232
*/
3333
language?: string | RetrieveCurrentLanguage;
3434
/**
35-
* Sets the optional fallback to use.
35+
* Sets the fallback language to be used when a translation
36+
* is not available in the current language.
37+
*/
38+
fallbackLanguage?: string;
39+
/**
40+
* Sets the optional fallback to use when a translation is neither
41+
* available in the current language or {@link fallbackLanguage}.
3642
*/
3743
fallback?: TranslationFallback;
3844
}
@@ -48,7 +54,7 @@ export function setupLocalizer(config: LocaleConfig = {}): Localizable {
4854
const computeLang = config.language;
4955
const usedLang = typeof computeLang === 'function' ? computeLang(languages, defaultLang, 'en') : computeLang;
5056
const language = usedLang || defaultLang;
51-
return new Localizer(msgs, language, languages.length ? languages : [language], config.fallback);
57+
return new Localizer(msgs, language, languages.length ? languages : [language], config.fallbackLanguage, config.fallback);
5258
}
5359

5460
/**

src/plugins/piral-translate/src/localize.test.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('Localize Module', () => {
3232
expect(result).toBe('hiho');
3333
});
3434

35-
it('localizeLocal translates from the global translations if local not available', () => {
35+
it('localizeLocal translates from the global translations if local and fallback language are not available', () => {
3636
const localizer = new Localizer(messages, 'en');
3737
const result = localizer.localizeLocal(
3838
{
@@ -45,6 +45,19 @@ describe('Localize Module', () => {
4545
expect(result).toBe('hello');
4646
});
4747

48+
it('localizeLocal prioritzes fallback language over global translations', () => {
49+
const localizer = new Localizer(messages, 'de', undefined, 'en');
50+
const result = localizer.localizeLocal(
51+
{
52+
en: {
53+
fallback: 'fallback',
54+
},
55+
},
56+
'fallback'
57+
);
58+
expect(result).toBe('fallback');
59+
});
60+
4861
it('localizeGlobal translates from the global translations', () => {
4962
const localizer = new Localizer(messages, 'en');
5063
const result = localizer.localizeGlobal('hi');
@@ -69,6 +82,12 @@ describe('Localize Module', () => {
6982
expect(result).toBe('Hi {{name}}, welcome back');
7083
});
7184

85+
it('localizeGlobal uses fallback language', () => {
86+
const localizer = new Localizer(messages, 'de', undefined, 'en');
87+
const result = localizer.localizeGlobal('greeting', { name: 'fallback' });
88+
expect(result).toBe('Hi fallback, welcome back');
89+
});
90+
7291
it('localizeGlobal places missing string placeholder if not found', () => {
7392
const localizer = new Localizer(messages, 'en');
7493
const result = localizer.localizeGlobal('ho');

src/plugins/piral-translate/src/localize.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function defaultFallback(key: string, language: string): string {
1616

1717
function formatMessage<T extends object>(message: string, variables: T): string {
1818
return message.replace(/{{\s*([A-Za-z0-9_.]+)\s*}}/g, (_match: string, p1: string) => {
19-
return p1 in variables ? variables[p1] ?? '' : `{{${p1}}}`;
19+
return p1 in variables ? (variables[p1] ?? '') : `{{${p1}}}`;
2020
});
2121
}
2222

@@ -29,7 +29,8 @@ export class Localizer implements Localizable {
2929
constructor(
3030
messages: LocalizationMessages | NestedLocalizationMessages,
3131
public language: string,
32-
public languages: Array<string>,
32+
public languages: Array<string> = [language],
33+
private fallbackLanguage?: string,
3334
private fallback: TranslationFallback = defaultFallback,
3435
) {
3536
this.messages = flattenTranslations(messages);
@@ -73,8 +74,10 @@ export class Localizer implements Localizable {
7374

7475
private translateMessage<T extends object>(messages: LocalizationMessages, key: string, variables?: T) {
7576
const language = this.language;
77+
const fallbackLanguage = this.fallbackLanguage;
7678
const translations = language && messages[language];
77-
const translation = translations && translations[key];
79+
const fallbackTranslations = fallbackLanguage && messages[fallbackLanguage];
80+
const translation = (translations && translations[key]) || (fallbackTranslations && fallbackTranslations[key]);
7881
return translation && (variables ? formatMessage(translation, variables) : translation);
7982
}
8083
}

0 commit comments

Comments
 (0)