Skip to content

Commit 6271aab

Browse files
authored
Merge pull request #33 from sillsdev/tweaks_2
Chinese case and other tweaks (#33)
2 parents 3aa6898 + d2183c8 commit 6271aab

File tree

7 files changed

+135
-18
lines changed

7 files changed

+135
-18
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636

3737
# find-language is a dependency of langauge-chooser-react-mui so it will have been built in the build step
3838
- name: Run tests
39-
run: npx nx test @ethnolib/find-language
39+
run: npx nx run-many --all --target=test
4040

4141
- name: Set name and email for git so we can commit and tag
4242
run: |

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export function searchForLanguage(
4747
const allResultsFuse = new Fuse(languages as ILanguage[], {
4848
...baseFuseOptions,
4949
ignoreLocation: true,
50-
threshold: 0.2,
50+
threshold: 0.3,
5151
});
5252
const allResults = allResultsFuse.search(queryString);
5353

components/language-chooser/common/find-language/searchResultModifiers.spec.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
import { expect, it, describe, test, beforeEach } from "vitest";
1+
import { expect, it, describe, test, beforeEach, beforeAll } from "vitest";
22
import {
33
filterScripts,
44
codeMatches,
55
prioritizeLangByKeywords,
66
filterLanguageCodes,
77
substituteInSpecialEntry,
8+
defaultSearchResultModifier,
89
} from "./searchResultModifiers";
910
import { ILanguage } from "./findLanguageInterfaces";
1011
import { createTestLanguageEntry } from "./testUtils";
12+
import { searchForLanguage } from "./searchForLanguage";
1113

1214
describe("filter scripts", () => {
1315
it("should filter out scripts", () => {
@@ -175,4 +177,28 @@ describe("reordering entries to prioritize desired language when keywords are se
175177
);
176178
expect(reorderedResults[0].iso639_3_code).toEqual("tpi");
177179
});
180+
181+
describe("Chinese should be handled reasonably", () => {
182+
let chineseResults: ILanguage[];
183+
beforeAll(() => {
184+
const chineseSearchString = "chinese";
185+
chineseResults = defaultSearchResultModifier(
186+
searchForLanguage(chineseSearchString),
187+
chineseSearchString
188+
);
189+
});
190+
it("top chinese result should have language subtag zh", () => {
191+
expect(chineseResults[0].languageSubtag).toEqual("zh");
192+
});
193+
it("should only have one zh result", () => {
194+
expect(
195+
chineseResults.filter((r) => r.languageSubtag === "zh").length
196+
).toEqual(1);
197+
});
198+
it("zh result should have many alternative names listed", () => {
199+
expect(
200+
chineseResults.find((r) => r.languageSubtag === "zh")?.names.length
201+
).toBeGreaterThan(10);
202+
});
203+
});
178204
});

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

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ export function filterScripts(
2121
}));
2222
}
2323

24+
export function modifyScripts(
25+
scriptModifier: (value: IScript) => IScript,
26+
results: ILanguage[]
27+
): ILanguage[] {
28+
return results.map((result) => ({
29+
...result,
30+
scripts: result.scripts.map(scriptModifier),
31+
}));
32+
}
33+
2434
const SCRIPT_CODES_TO_EXCLUDE = new Set([
2535
"Brai",
2636
"Zyyy",
@@ -72,6 +82,27 @@ function simplifyFrenchResult(results: ILanguage[]): ILanguage[] {
7282
return substituteInSpecialEntry("fra", getSpecialEntry, results);
7383
}
7484

85+
function simplifyChineseResult(results: ILanguage[]): ILanguage[] {
86+
function getSpecialEntry(result: ILanguage) {
87+
return {
88+
...result,
89+
regionNames: "", // clear the long and confusing list of region names
90+
scripts: [
91+
{
92+
code: "Hans",
93+
name: "Chinese (Simplified)",
94+
} as IScript,
95+
{
96+
code: "Hant",
97+
name: "Chinese (Traditional)",
98+
} as IScript,
99+
latinScriptData,
100+
],
101+
} as ILanguage;
102+
}
103+
return substituteInSpecialEntry("zho", getSpecialEntry, results);
104+
}
105+
75106
// Compare codes, ignoring any demarcation or casing
76107
// undefined does not match undefined
77108
export function codeMatches(
@@ -126,13 +157,26 @@ const ANCIENT_LANGUAGE_ENTRY_CODES = new Set([
126157
// Filter for deprecated, historical languages etc.
127158
]);
128159

160+
const SPECIAL_CASE_EXCLUDED_ENTRY_CODES = new Set([
161+
"zhx", // I don't understand why this entry is in langtags.json. It is an ISO-639-5 (language collection) code covering the zho macrolanguage, has no Ethnologue entry, only listed script is Nshu
162+
"cmn", // TODO when we implement macrolanguage handling, see if the situation is taken care of and we can remove this exception.
163+
// In langtags.json, most chinese entries have iso639_3_code "zho" (which is the macrolanguage code) except zh-Brai-CN and zh-Hant-ES which have "cmn"
164+
// so we end up with two search results and don't want to keep the "cmn" one
165+
]);
166+
167+
const DEFAULT_EXCLUDED_ENTRY_CODES = new Set([
168+
...NOT_A_LANGUAGE_ENTRY_CODES,
169+
...ANCIENT_LANGUAGE_ENTRY_CODES,
170+
...SPECIAL_CASE_EXCLUDED_ENTRY_CODES,
171+
]);
172+
129173
export function filterOutDefaultExcludedLanguages(
130174
results: ILanguage[]
131175
): ILanguage[] {
132176
return filterLanguageCodes(
133-
((code) =>
134-
!NOT_A_LANGUAGE_ENTRY_CODES.has(code) &&
135-
!ANCIENT_LANGUAGE_ENTRY_CODES.has(code)) as (value: string) => boolean,
177+
((code) => !DEFAULT_EXCLUDED_ENTRY_CODES.has(code)) as (
178+
value: string
179+
) => boolean,
136180
results
137181
);
138182
}
@@ -186,8 +230,15 @@ export function defaultSearchResultModifier(
186230
"fra",
187231
modifiedResults
188232
);
233+
modifiedResults = prioritizeLangByKeywords(
234+
["chinese"],
235+
searchString,
236+
"zho", // TODO: if we implement improved macrolanguage handling, see if we should change this to cmn
237+
modifiedResults
238+
);
189239
modifiedResults = simplifyEnglishResult(modifiedResults);
190240
modifiedResults = simplifyFrenchResult(modifiedResults);
241+
modifiedResults = simplifyChineseResult(modifiedResults);
191242
modifiedResults = filterOutDefaultExcludedLanguages(modifiedResults);
192243
modifiedResults = filterScripts(scriptFilter, modifiedResults);
193244
return modifiedResults;

components/language-chooser/react/common/language-chooser-react-hook/useLanguageChooser.ts

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,18 +147,56 @@ export const useLanguageChooser = (
147147
language.scripts.length === 1 ? language.scripts[0] : undefined
148148
);
149149
setCustomizableLanguageDetails({
150-
displayName: stripDemarcation(
151-
language.autonym || language.exonym || ""
152-
),
150+
displayName: defaultDisplayName(language),
153151
} as ICustomizableLanguageDetails);
154152
}
155153
}
156154

157155
function toggleSelectScript(script: IScript) {
156+
// clicking on the selected script unselects it
158157
if (codeMatches(script.code, selectedScript?.code)) {
159-
// clicking on the selected script unselects it
158+
// if the display name is our automatically set Chinese (Simplified) for zh-Hans or Chinese (Traditional) for zh-Hant,
159+
// then we want to reset to the default display name for Chinese with no selected script
160+
if (
161+
selectedLanguage?.languageSubtag === "zh" &&
162+
((codeMatches(script.code, "Hans") &&
163+
customizableLanguageDetails.displayName === "Chinese (Simplified)") ||
164+
(codeMatches(script.code, "Hant") &&
165+
customizableLanguageDetails.displayName ===
166+
"Chinese (Traditional)"))
167+
) {
168+
setCustomizableLanguageDetails((d) => ({
169+
...d,
170+
displayName: defaultDisplayName(selectedLanguage),
171+
}));
172+
}
160173
setSelectedScript(undefined);
161174
} else {
175+
// selecting a script
176+
if (
177+
selectedLanguage?.languageSubtag === "zh" &&
178+
customizableLanguageDetails.displayName ===
179+
defaultDisplayName(selectedLanguage)
180+
) {
181+
// automatically set the display name to Chinese (Simplified) or Chinese (Traditional) for zh-Hans or zh-Hant respectively
182+
if (codeMatches(script.code, "Hans")) {
183+
setCustomizableLanguageDetails(
184+
(d) =>
185+
({
186+
...d,
187+
displayName: "Chinese (Simplified)",
188+
}) as ICustomizableLanguageDetails
189+
);
190+
} else if (codeMatches(script.code, "Hant")) {
191+
setCustomizableLanguageDetails(
192+
(d) =>
193+
({
194+
...d,
195+
displayName: "Chinese (Traditional)",
196+
}) as ICustomizableLanguageDetails
197+
);
198+
}
199+
}
162200
setSelectedScript(script);
163201
}
164202
}
@@ -191,3 +229,7 @@ export const useLanguageChooser = (
191229
resetTo,
192230
} as ILanguageChooser;
193231
};
232+
233+
export function defaultDisplayName(language: ILanguage) {
234+
return stripDemarcation(language.autonym || language.exonym || "");
235+
}

components/language-chooser/react/language-chooser-react-mui/src/demos/DialogDemo.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { css } from "@emotion/react";
33
import { defaultSearchResultModifier } from "@ethnolib/find-language";
44
import { Button, Card, Dialog, Typography } from "@mui/material";
55
import {
6+
defaultDisplayName,
67
IOrthography,
78
parseLangtagFromLangChooser,
89
} from "@ethnolib/language-chooser-react-hook";
@@ -22,10 +23,12 @@ export const DialogDemo: React.FunctionComponent<{
2223
// To demonstrate the ability to reopen to a desired state
2324
const initialSelection: IOrthography | undefined =
2425
parseLangtagFromLangChooser(props.initialLanguageTag || "");
25-
if (props.initialCustomDisplayName !== undefined && initialSelection) {
26+
if (initialSelection?.language) {
2627
initialSelection.customDetails = {
27-
...initialSelection.customDetails,
28-
displayName: props.initialCustomDisplayName,
28+
...(initialSelection.customDetails || []),
29+
displayName:
30+
props.initialCustomDisplayName ??
31+
defaultDisplayName(initialSelection.language),
2932
};
3033
}
3134

components/language-chooser/react/language-chooser-react-mui/tsconfig.storybook.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@
44
"emitDecoratorMetadata": true,
55
"outDir": ""
66
},
7-
"files": [
8-
"../../../../node_modules/@nx/react/typings/styled-jsx.d.ts",
9-
"../../../../node_modules/@nx/react/typings/cssmodule.d.ts",
10-
"../../../../node_modules/@nx/react/typings/image.d.ts"
11-
],
127
"exclude": [
138
"src/**/*.spec.ts",
149
"src/**/*.test.ts",

0 commit comments

Comments
 (0)