fix(app): localize provider usage plurals

This commit is contained in:
Michael Wu
2026-10-03 05:07:05 +09:00
parent 1b65afe2b9
commit c211d7af97
4 changed files with 67 additions and 2 deletions
+36
View File
@@ -1972,8 +1972,26 @@ export const ar: TranslationResources = {
},
duration: {
days: "{{value}} يوم",
days_zero: "{{value}} يوم",
days_one: "يوم واحد",
days_two: "يومين",
days_few: "{{value}} أيام",
days_many: "{{value}} يومًا",
days_other: "{{value}} يوم",
hours: "{{value}} ساعة",
hours_zero: "{{value}} ساعة",
hours_one: "ساعة واحدة",
hours_two: "ساعتين",
hours_few: "{{value}} ساعات",
hours_many: "{{value}} ساعة",
hours_other: "{{value}} ساعة",
minutes: "{{value}} دقيقة",
minutes_zero: "{{value}} دقيقة",
minutes_one: "دقيقة واحدة",
minutes_two: "دقيقتين",
minutes_few: "{{value}} دقائق",
minutes_many: "{{value}} دقيقة",
minutes_other: "{{value}} دقيقة",
},
timing: {
resettingNow: "تتم إعادة التعيين الآن",
@@ -1982,8 +2000,26 @@ export const ar: TranslationResources = {
runsOutIn: "ينفد خلال {{duration}}",
justNow: "الآن",
daysAgo: "قبل {{value}} يومًا",
daysAgo_zero: "قبل {{value}} يوم",
daysAgo_one: "قبل يوم واحد",
daysAgo_two: "قبل يومين",
daysAgo_few: "قبل {{value}} أيام",
daysAgo_many: "قبل {{value}} يومًا",
daysAgo_other: "قبل {{value}} يوم",
hoursAgo: "قبل {{value}} ساعة",
hoursAgo_zero: "قبل {{value}} ساعة",
hoursAgo_one: "قبل ساعة واحدة",
hoursAgo_two: "قبل ساعتين",
hoursAgo_few: "قبل {{value}} ساعات",
hoursAgo_many: "قبل {{value}} ساعة",
hoursAgo_other: "قبل {{value}} ساعة",
minutesAgo: "قبل {{value}} دقيقة",
minutesAgo_zero: "قبل {{value}} دقيقة",
minutesAgo_one: "قبل دقيقة واحدة",
minutesAgo_two: "قبل دقيقتين",
minutesAgo_few: "قبل {{value}} دقائق",
minutesAgo_many: "قبل {{value}} دقيقة",
minutesAgo_other: "قبل {{value}} دقيقة",
updated: "تم التحديث {{relativeTime}}",
},
},
+15 -1
View File
@@ -2913,4 +2913,18 @@ type WidenStringLeaves<T> = {
[K in keyof T]: T[K] extends string ? string : WidenStringLeaves<T[K]>;
};
export type TranslationResources = WidenStringLeaves<typeof en>;
type TranslationResourcesBase = WidenStringLeaves<typeof en>;
type PluralCategory = "zero" | "one" | "two" | "few" | "many" | "other";
type DurationPluralKey = `${"days" | "hours" | "minutes"}_${PluralCategory}`;
type AgoPluralKey = `${"daysAgo" | "hoursAgo" | "minutesAgo"}_${PluralCategory}`;
// i18next plural categories differ by locale, so locale catalogs may add the
// explicit v4 suffixes they need while retaining the canonical fallback keys.
export type TranslationResources = TranslationResourcesBase & {
providerUsage: TranslationResourcesBase["providerUsage"] & {
duration: TranslationResourcesBase["providerUsage"]["duration"] &
Partial<Record<DurationPluralKey, string>>;
timing: TranslationResourcesBase["providerUsage"]["timing"] &
Partial<Record<AgoPluralKey, string>>;
};
};
+16
View File
@@ -51,4 +51,20 @@ describe("formatAmount", () => {
expect(formatRunsOutLabel(daysFromNow, NOW)).toBe("s’épuise dans 1\u202f234 j");
expect(formatAgo(daysAgo, NOW)).toBe("il y a 1\u202f234 j");
});
it("selects Arabic plural forms for relative durations", async () => {
await i18n.changeLanguage("ar");
const twoHoursFromNow = new Date(NOW + 2 * 60 * 60 * 1000).toISOString();
const threeHoursFromNow = new Date(NOW + 3 * 60 * 60 * 1000).toISOString();
const twoDaysAgo = new Date(NOW - 2 * 24 * 60 * 60 * 1000).toISOString();
expect(formatResetLabel(twoHoursFromNow)).toBe("تتم إعادة التعيين خلال ساعتين");
expect(formatRunsOutLabel(threeHoursFromNow)).toBe("ينفد خلال 3 ساعات");
expect(formatAgo(twoDaysAgo)).toBe("قبل يومين");
});
it("uses locale-aware compact notation for token balances", () => {
expect(formatAmount(1_234, "tokens", "en")).toBe("1.2K");
expect(formatAmount(1_234, "tokens", "ar")).toBe("1.2\u00a0ألف");
});
});
-1
View File
@@ -1,4 +1,3 @@
import { formatTokenCount } from "@/components/context-window-meter.utils";
import { i18n } from "@/i18n/i18next";
import type { UsageDisplayAs } from "./preferences";
import type { UsageBalanceUnit } from "./types";