mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-23 18:17:44 +02:00
* i18n: add japanese locale * fix: spacing issues * refactor * fix(desktop): set <html lang> before paint to avoid JA Kanji font flash Switch the documentElement.lang sync from useEffect to useLayoutEffect so lang is committed before the first paint. Otherwise Japanese desktop users saw one frame of Kanji rendered with the Chinese-first fallback stack before the html[lang|="ja"] CJK override applied. Also fix the stale selector in the HTML_LANG comment (html[lang^="ja"] -> html[lang|="ja"]). Addresses review nits on MUL-2893. Co-authored-by: multica-agent <github@multica.ai> * fix(docs): tokenize the ideographic iteration mark in JA search Add U+3005 (々) to the Japanese search tokenizer character class. It sits just below the kana blocks, so words like 様々 / 日々 / 個々 previously dropped the mark and split awkwardly, hurting recall. Addresses a review nit on MUL-2893. Co-authored-by: multica-agent <github@multica.ai> * fix(i18n): restore ja locale parity after merging main Merging main brought new EN strings into agents/chat/onboarding/settings/ squads that the ja bundle (authored against an older snapshot) lacked, breaking the locales parity test. Add the Japanese translations for the new keys (workspace logo upload, agents runtime filter, chat session-history stop dialog, onboarding social_github, squad archived status) and drop the two renamed chat window keys (active_group / archived_group) that EN removed in favour of history_group. Fixes the failing @multica/views parity.test.ts on the FE CI for MUL-2893. Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: J <j@multica.ai> Co-authored-by: multica-agent <github@multica.ai>
148 lines
4.4 KiB
TypeScript
148 lines
4.4 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const mockUseCasesSource = vi.hoisted(() => ({
|
|
getPages: vi.fn(),
|
|
getPage: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("fumadocs-core/source", () => ({
|
|
loader: vi.fn(() => mockUseCasesSource),
|
|
}));
|
|
|
|
vi.mock("@/.source", () => ({
|
|
useCases: {
|
|
toFumadocsSource: vi.fn(() => ({})),
|
|
},
|
|
}));
|
|
|
|
import { mergeUseCasePagesWithEnglishFallback } from "./use-case-locale-fallback";
|
|
import {
|
|
getUseCasePageForLocale,
|
|
getUseCasePagesForLocale,
|
|
useCasesSource,
|
|
} from "./use-cases-source";
|
|
|
|
beforeEach(() => {
|
|
vi.mocked(useCasesSource.getPages).mockReset();
|
|
vi.mocked(useCasesSource.getPage).mockReset();
|
|
});
|
|
|
|
describe("mergeUseCasePagesWithEnglishFallback", () => {
|
|
it("keeps localized pages ahead of English fallback pages", () => {
|
|
const localizedPages = [
|
|
{ slugs: ["localized"], data: { title: "Localized" } },
|
|
];
|
|
const englishPages = [
|
|
{ slugs: ["localized"], data: { title: "English duplicate" } },
|
|
{ slugs: ["english-only"], data: { title: "English only" } },
|
|
];
|
|
|
|
expect(
|
|
mergeUseCasePagesWithEnglishFallback(localizedPages, englishPages),
|
|
).toEqual([
|
|
{ slugs: ["localized"], data: { title: "Localized" } },
|
|
{ slugs: ["english-only"], data: { title: "English only" } },
|
|
]);
|
|
});
|
|
|
|
it("dedupes nested slugs by full path", () => {
|
|
const localizedPages = [{ slugs: ["teams", "ops"] }];
|
|
const englishPages = [
|
|
{ slugs: ["teams", "ops"] },
|
|
{ slugs: ["teams", "support"] },
|
|
];
|
|
|
|
expect(
|
|
mergeUseCasePagesWithEnglishFallback(localizedPages, englishPages).map(
|
|
(page) => page.slugs.join("/"),
|
|
),
|
|
).toEqual(["teams/ops", "teams/support"]);
|
|
});
|
|
});
|
|
|
|
describe("use case source locale fallback", () => {
|
|
it("keeps localized and English-only pages in the production index wrapper", () => {
|
|
const localizedPage = {
|
|
slugs: ["localized"],
|
|
data: { title: "Localized" },
|
|
};
|
|
const englishDuplicate = {
|
|
slugs: ["localized"],
|
|
data: { title: "English duplicate" },
|
|
};
|
|
const englishOnly = {
|
|
slugs: ["english-only"],
|
|
data: { title: "English only" },
|
|
};
|
|
|
|
vi.mocked(useCasesSource.getPages).mockImplementation((lang?: string) => {
|
|
if (lang === "ko") {
|
|
return [localizedPage] as ReturnType<typeof useCasesSource.getPages>;
|
|
}
|
|
if (lang === "en") {
|
|
return [
|
|
englishDuplicate,
|
|
englishOnly,
|
|
] as ReturnType<typeof useCasesSource.getPages>;
|
|
}
|
|
return [] as ReturnType<typeof useCasesSource.getPages>;
|
|
});
|
|
|
|
expect(
|
|
getUseCasePagesForLocale("ko").map((page) => page.slugs.join("/")),
|
|
).toEqual(["localized", "english-only"]);
|
|
});
|
|
|
|
it("maps the ja locale to the ja use-case lang and keeps the English fallback", () => {
|
|
const localizedPage = {
|
|
slugs: ["localized"],
|
|
data: { title: "ローカライズ済み" },
|
|
};
|
|
const englishOnly = {
|
|
slugs: ["english-only"],
|
|
data: { title: "English only" },
|
|
};
|
|
|
|
vi.mocked(useCasesSource.getPages).mockImplementation((lang?: string) => {
|
|
if (lang === "ja") {
|
|
return [localizedPage] as ReturnType<typeof useCasesSource.getPages>;
|
|
}
|
|
if (lang === "en") {
|
|
return [englishOnly] as ReturnType<typeof useCasesSource.getPages>;
|
|
}
|
|
return [] as ReturnType<typeof useCasesSource.getPages>;
|
|
});
|
|
|
|
expect(
|
|
getUseCasePagesForLocale("ja").map((page) => page.slugs.join("/")),
|
|
).toEqual(["localized", "english-only"]);
|
|
});
|
|
|
|
it("falls back to English-only detail pages in the production detail wrapper", () => {
|
|
const localizedPage = {
|
|
slugs: ["localized"],
|
|
data: { title: "Localized" },
|
|
};
|
|
const englishOnly = {
|
|
slugs: ["english-only"],
|
|
data: { title: "English only" },
|
|
};
|
|
|
|
vi.mocked(useCasesSource.getPage).mockImplementation(
|
|
(slugs: string[] | undefined, lang?: string) => {
|
|
const key = `${lang}:${slugs?.join("/") ?? ""}`;
|
|
if (key === "ko:localized") {
|
|
return localizedPage as ReturnType<typeof useCasesSource.getPage>;
|
|
}
|
|
if (key === "en:english-only") {
|
|
return englishOnly as ReturnType<typeof useCasesSource.getPage>;
|
|
}
|
|
return undefined as ReturnType<typeof useCasesSource.getPage>;
|
|
},
|
|
);
|
|
|
|
expect(getUseCasePageForLocale(["localized"], "ko")).toBe(localizedPage);
|
|
expect(getUseCasePageForLocale(["english-only"], "ko")).toBe(englishOnly);
|
|
});
|
|
});
|