fix(i18n): harden owner localized forms
This commit is contained in:
@@ -56,14 +56,6 @@ export type CalendarEventItem = {
|
|||||||
translations?: Record<string, Record<string, string>>;
|
translations?: Record<string, Record<string, string>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const typeLabels = {
|
|
||||||
meeting: "Toplantı",
|
|
||||||
focus: "Odak",
|
|
||||||
deadline: "Deadline",
|
|
||||||
personal: "Kişisel",
|
|
||||||
finance: "Finans",
|
|
||||||
};
|
|
||||||
|
|
||||||
const typeClasses = {
|
const typeClasses = {
|
||||||
meeting: "border-blue-200 bg-blue-50 text-blue-700",
|
meeting: "border-blue-200 bg-blue-50 text-blue-700",
|
||||||
focus: "border-emerald-200 bg-emerald-50 text-emerald-700",
|
focus: "border-emerald-200 bg-emerald-50 text-emerald-700",
|
||||||
@@ -251,7 +243,7 @@ function EventList({
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<Badge className={typeClasses[event.type]}>{t(`calendar.types.${event.type}` as any)}</Badge>
|
<Badge className={typeClasses[event.type]}>{t(`calendar.types.${event.type}`)}</Badge>
|
||||||
</div>
|
</div>
|
||||||
{!compact ? (
|
{!compact ? (
|
||||||
<div className="mt-3 flex gap-2">
|
<div className="mt-3 flex gap-2">
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ export function ClientsClient({
|
|||||||
return (
|
return (
|
||||||
<DroppableColumn
|
<DroppableColumn
|
||||||
key={stage.id}
|
key={stage.id}
|
||||||
title={t(`clients.pipeline.${stage.id}` as any)}
|
title={t(`clients.pipeline.${stage.id}`)}
|
||||||
count={stageClients.length}
|
count={stageClients.length}
|
||||||
color={stage.color.split(' ')[1]}
|
color={stage.color.split(' ')[1]}
|
||||||
onDrop={() => handleDrop(stage.id)}
|
onDrop={() => handleDrop(stage.id)}
|
||||||
@@ -383,7 +383,7 @@ function ClientRow({ client, activeLocales }: { client: ClientListItem, activeLo
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Badge className={stage.color}>
|
<Badge className={stage.color}>
|
||||||
{t(`clients.pipeline.${stage.id}` as any)}
|
{t(`clients.pipeline.${stage.id}`)}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -528,7 +528,7 @@ function ClientFormFields({ client, activeLocales }: { client?: ClientListItem,
|
|||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{pipelineStages.map(stage => (
|
{pipelineStages.map(stage => (
|
||||||
<SelectItem key={stage.id} value={stage.id}>{t(`clients.pipeline.${stage.id}` as any)}</SelectItem>
|
<SelectItem key={stage.id} value={stage.id}>{t(`clients.pipeline.${stage.id}`)}</SelectItem>
|
||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|||||||
@@ -73,12 +73,14 @@ export type ProjectListItem = {
|
|||||||
translations?: LocalizedFieldValues;
|
translations?: LocalizedFieldValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
const typeLabels = (t: any) => ({
|
type Translate = ReturnType<typeof useTranslations>;
|
||||||
|
|
||||||
|
const typeLabels = (t: Translate) => ({
|
||||||
client_project: t("projects.types.client"),
|
client_project: t("projects.types.client"),
|
||||||
side_project: t("projects.types.side"),
|
side_project: t("projects.types.side"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const statusLabels = (t: any) => ({
|
const statusLabels = (t: Translate) => ({
|
||||||
planning: t("projects.status.planning"),
|
planning: t("projects.status.planning"),
|
||||||
active: t("projects.status.active"),
|
active: t("projects.status.active"),
|
||||||
paused: t("projects.status.paused"),
|
paused: t("projects.status.paused"),
|
||||||
@@ -605,7 +607,11 @@ function ProjectFormFields({
|
|||||||
idPrefix={`project-${project?.id || "new"}`}
|
idPrefix={`project-${project?.id || "new"}`}
|
||||||
defaultLocale={localization.defaultLocale}
|
defaultLocale={localization.defaultLocale}
|
||||||
locales={localization.locales}
|
locales={localization.locales}
|
||||||
fields={contentTranslationRegistry.project.map((f: any) => ({ ...f, label: (t as any)(`projects.fields.${f.name}`) || f.label, placeholder: f.placeholder ? (t as any)(`projects.placeholders.${f.name}`) || f.placeholder : undefined }))}
|
fields={contentTranslationRegistry.project.map((f) => ({
|
||||||
|
...f,
|
||||||
|
label: t(`projects.fields.${f.name}`) || f.label,
|
||||||
|
placeholder: f.placeholder ? t(`projects.placeholders.${f.name}`) || f.placeholder : undefined,
|
||||||
|
}))}
|
||||||
values={project?.translations}
|
values={project?.translations}
|
||||||
fallbackValues={{
|
fallbackValues={{
|
||||||
name: project?.name,
|
name: project?.name,
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ export function TranslationEditor({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Select value={filter} onValueChange={(v: any) => setFilter(v)}>
|
<Select value={filter} onValueChange={(value) => setFilter(value as typeof filter)}>
|
||||||
<SelectTrigger className="w-[140px]">
|
<SelectTrigger className="w-[140px]">
|
||||||
<SelectValue />
|
<SelectValue />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ export async function importTranslationsAction(content: string) {
|
|||||||
service.importPackage(actor, data);
|
service.importPackage(actor, data);
|
||||||
revalidatePath("/settings/languages");
|
revalidatePath("/settings/languages");
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error: any) {
|
} catch (error) {
|
||||||
console.error("Import error:", error);
|
console.error("Import error:", error);
|
||||||
return { errorKey: "common.error.description", details: error.message };
|
return { errorKey: "common.error.description", details: error instanceof Error ? error.message : String(error) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,19 +60,6 @@ export type TaskListItem = {
|
|||||||
translations?: LocalizedFieldValues;
|
translations?: LocalizedFieldValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
const statusLabels = {
|
|
||||||
todo: "Yapılacak",
|
|
||||||
in_progress: "Devam ediyor",
|
|
||||||
done: "Tamamlandı",
|
|
||||||
};
|
|
||||||
|
|
||||||
const priorityLabels = {
|
|
||||||
low: "Düşük",
|
|
||||||
medium: "Orta",
|
|
||||||
high: "Yüksek",
|
|
||||||
urgent: "Acil",
|
|
||||||
};
|
|
||||||
|
|
||||||
const priorityClasses = {
|
const priorityClasses = {
|
||||||
low: "border-zinc-200 bg-zinc-50 text-zinc-700",
|
low: "border-zinc-200 bg-zinc-50 text-zinc-700",
|
||||||
medium: "border-blue-200 bg-blue-50 text-blue-700",
|
medium: "border-blue-200 bg-blue-50 text-blue-700",
|
||||||
@@ -687,7 +674,11 @@ function TaskFormFields({
|
|||||||
idPrefix={`task-${task?.id || "new"}`}
|
idPrefix={`task-${task?.id || "new"}`}
|
||||||
defaultLocale={localization.defaultLocale}
|
defaultLocale={localization.defaultLocale}
|
||||||
locales={localization.locales}
|
locales={localization.locales}
|
||||||
fields={contentTranslationRegistry.task.map((f: any) => ({ ...f, label: (t as any)(`tasks.fields.${f.name}`) || f.label, placeholder: f.placeholder ? (t as any)(`tasks.placeholders.${f.name}`) || f.placeholder : undefined }))}
|
fields={contentTranslationRegistry.task.map((f) => ({
|
||||||
|
...f,
|
||||||
|
label: t(`tasks.fields.${f.name}`) || f.label,
|
||||||
|
placeholder: f.placeholder ? t(`tasks.placeholders.${f.name}`) || f.placeholder : undefined,
|
||||||
|
}))}
|
||||||
values={task?.translations}
|
values={task?.translations}
|
||||||
fallbackValues={{
|
fallbackValues={{
|
||||||
title: task?.title,
|
title: task?.title,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import { compareCatalogKeys, I18N_NAMESPACES } from "../lib/i18n";
|
import { compareCatalogKeys } from "../lib/i18n";
|
||||||
import { trCatalog } from "../locales/tr";
|
import { trCatalog } from "../locales/tr";
|
||||||
import { enCatalog } from "../locales/en";
|
import { enCatalog } from "../locales/en";
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ for (const page of authPages) {
|
|||||||
assert.equal(content.includes("resolvePublicLocale"), true, `${page} missing resolvePublicLocale`);
|
assert.equal(content.includes("resolvePublicLocale"), true, `${page} missing resolvePublicLocale`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = compareCatalogKeys(trCatalog as any, enCatalog as any, ["auth"]);
|
const result = compareCatalogKeys(trCatalog, enCatalog, ["auth"]);
|
||||||
|
|
||||||
const authMissingInEn = result.missingInRight.filter((k: string) => k.startsWith("auth."));
|
const authMissingInEn = result.missingInRight.filter((k: string) => k.startsWith("auth."));
|
||||||
const authMissingInTr = result.missingInLeft.filter((k: string) => k.startsWith("auth."));
|
const authMissingInTr = result.missingInLeft.filter((k: string) => k.startsWith("auth."));
|
||||||
|
|||||||
@@ -219,6 +219,7 @@ export const revisionCreateSchema = z.object({
|
|||||||
id: resourceIdSchema.optional(),
|
id: resourceIdSchema.optional(),
|
||||||
projectId: resourceIdSchema,
|
projectId: resourceIdSchema,
|
||||||
description: z.string().trim().min(1).max(20_000),
|
description: z.string().trim().min(1).max(20_000),
|
||||||
|
sourceLocale: z.string().trim().min(2).max(12).nullable().optional(),
|
||||||
});
|
});
|
||||||
export const revisionStatusSchema = z.enum(revisionStatuses);
|
export const revisionStatusSchema = z.enum(revisionStatuses);
|
||||||
|
|
||||||
|
|||||||
@@ -433,6 +433,7 @@ export class DomainService {
|
|||||||
clientId: scope.clientId,
|
clientId: scope.clientId,
|
||||||
requestedByUserId: scope.authUserId,
|
requestedByUserId: scope.authUserId,
|
||||||
description: value.description,
|
description: value.description,
|
||||||
|
sourceLocale: value.sourceLocale,
|
||||||
}).returning().get();
|
}).returning().get();
|
||||||
}, { behavior: "immediate" });
|
}, { behavior: "immediate" });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user