Localization stages 2-3: drafts, publishing, translation editor
- games.main_version_id, version visibility (draft/published) and kind
(original/translation/mod), version_history; migration 0002
- permissions translations.edit and versions.publish
- "Translate" creates a translation draft; publishing merges the changed
languages into the main version in place (players keep their saves), the
previous manifest goes to the history and can be restored
- translation API: overview with per-state stats, entries with filters,
search and scene context, save, glossary, locale font, PO/CSV export/import
- translation editor page: languages and progress, lines and strings,
filters, autosave, approve/outdated/fuzzy actions, glossary highlighting,
"play from here" with the scene restored
- player: ?lang= and ?at= from the editor, per-locale font
(models.py and permissions.py for this landed earlier in 9ee3e1f)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e047f3aa0
commit
ac164d1782
20 files changed
+2039
-298
No files matched your search
@@ -7,6 +7,7 @@ export interface LocaleInfo {
|
||||
renpy: string;
|
||||
modules: Record<string, string>;
|
||||
strings: string;
|
||||
font?: string | null;
|
||||
lines: number;
|
||||
progress: number;
|
||||
}
|
||||
@@ -24,6 +25,7 @@ export class Translator {
|
||||
public readonly renpyName: string | null,
|
||||
private lines: Map<string, string> = new Map(),
|
||||
private strings: Map<string, string> = new Map(),
|
||||
public readonly font: string | null = null, // logical path of the locale's font
|
||||
) {}
|
||||
|
||||
static source(game: GameData) {
|
||||
@@ -77,11 +79,13 @@ export async function loadTranslator(game: GameData, manifest: Manifest, lang: s
|
||||
return r.json() as Promise<Record<string, Entry>>;
|
||||
});
|
||||
};
|
||||
const [strings, ...modules] = await Promise.all([blob(info.strings), ...Object.values(info.modules).map(blob)]);
|
||||
const [strings, ...modules] = await Promise.all([
|
||||
info.strings ? blob(info.strings) : Promise.resolve({} as Record<string, Entry>),
|
||||
...Object.values(info.modules).map(blob)]);
|
||||
const lines = new Map<string, string>();
|
||||
for (const mod of modules) for (const [tid, e] of Object.entries(mod)) lines.set(tid, e.t);
|
||||
return new Translator(lang, info.renpy, lines,
|
||||
new Map(Object.entries(strings).map(([k, e]) => [k, e.t])));
|
||||
new Map(Object.entries(strings).map(([k, e]) => [k, e.t])), info.font ?? null);
|
||||
}
|
||||
|
||||
export function languageName(game: GameData, lang: string): string {
|
||||
|
||||
Reference in new issue
Block a user