Skip to content

Commit 970e44a

Browse files
authored
Merge pull request #152 from sillsdev/rtl
fix: populate script isRtl in controller and svelte
2 parents f723983 + 6b5cf77 commit 970e44a

4 files changed

Lines changed: 56 additions & 15 deletions

File tree

components/language-chooser/common/find-language/findLanguageInterfaces.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,14 @@ export interface IOrthography {
7272
// isRtl setting to match its IScript in every case, which can accomplish
7373
// with und-{script}.
7474
export function isRTLScript(scriptCode: string): boolean {
75-
const locale = new Intl.Locale(`und-${scriptCode}`);
76-
// getTextInfo is the standardized property; textInfo is the older name
77-
const info = locale.getTextInfo?.() ?? (locale as any).textInfo;
78-
return info?.direction === "rtl";
75+
try {
76+
const locale = new Intl.Locale(`und-${scriptCode}`);
77+
// getTextInfo is the standardized property; textInfo is the older name
78+
const info = locale.getTextInfo?.() ?? (locale as any).textInfo;
79+
return info?.direction === "rtl";
80+
} catch {
81+
// An unrecognized/malformed script code makes Intl.Locale throw. Such a
82+
// script has no known RTL direction, so treat it as not RTL.
83+
return false;
84+
}
7985
}

components/language-chooser/common/language-chooser-controller/src/view-models/language-chooser.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
type IRegion,
1010
type IScript,
1111
isManuallyEnteredTagLanguage,
12+
isRTLScript,
1213
isUnlistedLanguage,
1314
isValidBcp47Tag,
1415
languageForManuallyEnteredTag,
@@ -118,7 +119,7 @@ export function useLanguageChooserViewModel(
118119
if (selectedLang.scripts.length === 1) {
119120
// Automatically select a language's only script
120121
_setScriptList([]);
121-
selectedScript.value = selectedLang.scripts[0];
122+
selectedScript.value = scriptWithReadingDirection(selectedLang.scripts[0]);
122123
} else {
123124
_setScriptList(selectedLang.scripts);
124125
}
@@ -135,7 +136,9 @@ export function useLanguageChooserViewModel(
135136

136137
function _onScriptSelected(index: number) {
137138
selectItem(index, listedScripts.value);
138-
selectedScript.value = listedScripts.value[index].script;
139+
selectedScript.value = scriptWithReadingDirection(
140+
listedScripts.value[index].script
141+
);
139142
_onOrthographyChanged();
140143
}
141144

@@ -271,7 +274,9 @@ export function useLanguageChooserViewModel(
271274
region?: IRegion;
272275
dialect?: string;
273276
}) {
274-
selectedScript.requestUpdate(script);
277+
selectedScript.requestUpdate(
278+
script ? scriptWithReadingDirection(script) : script
279+
);
275280
customizations.requestUpdate({
276281
region,
277282
dialect,
@@ -308,6 +313,13 @@ export function useLanguageChooserViewModel(
308313
};
309314
}
310315

316+
// Returns a copy of the script with its reading direction (isRtl) populated,
317+
// so consumers receive the direction as part of the selected orthography.
318+
// Mirrors the behavior of the React useLanguageChooser hook.
319+
function scriptWithReadingDirection(script: IScript): IScript {
320+
return { ...script, isRtl: isRTLScript(script.code) };
321+
}
322+
311323
function hasValidDisplayName(selection: IOrthography) {
312324
if (!selection.language) {
313325
return false;

components/language-chooser/common/language-chooser-controller/test/language-chooser.spec.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,10 @@ describe("selected script", () => {
336336
test.viewModel.listedLanguages.value[0].isSelected.requestUpdate(true);
337337
test.viewModel.listedScripts.value[0].isSelected.requestUpdate(true);
338338

339-
expect(test.viewModel.selectedScript.value).toEqual(
340-
NorthernUzbekLanguage.scripts[0]
341-
);
339+
expect(test.viewModel.selectedScript.value).toEqual({
340+
...NorthernUzbekLanguage.scripts[0],
341+
isRtl: false,
342+
});
342343
});
343344

344345
it("should be undefined after script deselected", () => {
@@ -366,9 +367,20 @@ describe("selected script", () => {
366367

367368
test.viewModel.listedLanguages.value[0].isSelected.requestUpdate(true);
368369

369-
expect(test.viewModel.selectedScript.value).toEqual(
370-
WaataLanguage.scripts[0]
371-
);
370+
expect(test.viewModel.selectedScript.value).toEqual({
371+
...WaataLanguage.scripts[0],
372+
isRtl: false,
373+
});
374+
});
375+
376+
it("should populate isRtl for a right-to-left script", () => {
377+
const test = new TestHelper({ initialLanguages: [NorthernUzbekLanguage] });
378+
379+
test.viewModel.listedLanguages.value[0].isSelected.requestUpdate(true);
380+
// NorthernUzbekLanguage.scripts[1] is Arabic, a right-to-left script
381+
test.viewModel.listedScripts.value[1].isSelected.requestUpdate(true);
382+
383+
expect(test.viewModel.selectedScript.value?.isRtl).toBe(true);
372384
});
373385
});
374386

@@ -626,7 +638,9 @@ describe("customize language modal", () => {
626638
scriptViewModel.isSelected.requestUpdate(true);
627639
t.viewModel.onCustomizeButtonClicked();
628640

629-
expect(spy).toHaveBeenCalledWith({ script: scriptViewModel.script });
641+
expect(spy).toHaveBeenCalledWith({
642+
script: { ...scriptViewModel.script, isRtl: false },
643+
});
630644
});
631645

632646
it("populates with dialect when custom dialect was selected", () => {
@@ -706,6 +720,7 @@ describe("customize language modal", () => {
706720
expect(t.viewModel.selectedScript.value).toEqual({
707721
code: "abc",
708722
name: "ABC Script",
723+
isRtl: false,
709724
});
710725
});
711726

components/language-chooser/svelte/language-chooser-svelte-daisyui/src/demos/BasicDemo.svelte

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,15 @@
7070

7171
<div>
7272
<div class="text-base-content/60">Script</div>
73-
<div>{orthography.script?.name || "-"}</div>
73+
<div>
74+
{#if orthography.script}
75+
{orthography.script.name} ({orthography.script.isRtl
76+
? "RTL"
77+
: "LTR"})
78+
{:else}
79+
-
80+
{/if}
81+
</div>
7482
</div>
7583

7684
<div>

0 commit comments

Comments
 (0)