replace static strings with translator calls

This commit is contained in:
Chris Kruining 2025-01-06 15:53:21 +01:00
parent b329b67a3e
commit 1f9aad755c
No known key found for this signature in database
GPG key ID: EB894A3560CCCAD2
5 changed files with 38 additions and 27 deletions

View file

@ -3,6 +3,7 @@ import { debounce, Mutation } from "~/utilities";
import { Column, GridApi as GridCompApi, Grid as GridComp } from "~/components/grid"; import { Column, GridApi as GridCompApi, Grid as GridComp } from "~/components/grid";
import { createDataSet, DataSetNode, DataSetRowNode } from "~/components/table"; import { createDataSet, DataSetNode, DataSetRowNode } from "~/components/table";
import { SelectionItem } from "../selectable"; import { SelectionItem } from "../selectable";
import { useI18n } from "../i18n";
import css from "./grid.module.css" import css from "./grid.module.css"
export type Entry = { key: string } & { [lang: string]: string }; export type Entry = { key: string } & { [lang: string]: string };
@ -29,12 +30,14 @@ const groupBy = (rows: DataSetRowNode<number, Entry>[]) => {
} }
export function Grid(props: { class?: string, rows: Entry[], locales: string[], api?: (api: GridApi) => any }) { export function Grid(props: { class?: string, rows: Entry[], locales: string[], api?: (api: GridApi) => any }) {
const { t } = useI18n();
const rows = createMemo(() => createDataSet<Entry>(props.rows, { group: { by: 'key', with: groupBy } })); const rows = createMemo(() => createDataSet<Entry>(props.rows, { group: { by: 'key', with: groupBy } }));
const locales = createMemo(() => props.locales); const locales = createMemo(() => props.locales);
const columns = createMemo<Column<Entry>[]>(() => [ const columns = createMemo<Column<Entry>[]>(() => [
{ {
id: 'key', id: 'key',
label: 'Key', label: t('feature.file.grid.key'),
renderer: ({ value }) => value.split('.').at(-1), renderer: ({ value }) => value.split('.').at(-1),
}, },
...locales().map<Column<Entry>>(lang => ({ ...locales().map<Column<Entry>>(lang => ({

View file

@ -10,6 +10,7 @@ import { Tab, Tabs } from "~/components/tabs";
import { isServer } from "solid-js/web"; import { isServer } from "solid-js/web";
import { Prompt, PromptApi } from "~/components/prompt"; import { Prompt, PromptApi } from "~/components/prompt";
import EditBlankImage from '~/assets/edit-blank.svg' import EditBlankImage from '~/assets/edit-blank.svg'
import { useI18n } from "~/features/i18n";
import css from "./edit.module.css"; import css from "./edit.module.css";
const isInstalledPWA = !isServer && window.matchMedia('(display-mode: standalone)').matches; const isInstalledPWA = !isServer && window.matchMedia('(display-mode: standalone)').matches;
@ -72,6 +73,7 @@ export default function Edit(props: ParentProps) {
const Editor: Component<{ root: FileSystemDirectoryHandle }> = (props) => { const Editor: Component<{ root: FileSystemDirectoryHandle }> = (props) => {
const filesContext = useFiles(); const filesContext = useFiles();
const { t } = useI18n();
const tabs = createMemo(() => filesContext.files().map(({ key, handle }) => { const tabs = createMemo(() => filesContext.files().map(({ key, handle }) => {
const [api, setApi] = createSignal<(GridApi & { addLocale(locale: string): void })>(); const [api, setApi] = createSignal<(GridApi & { addLocale(locale: string): void })>();
@ -234,18 +236,18 @@ const Editor: Component<{ root: FileSystemDirectoryHandle }> = (props) => {
}); });
const commands = { const commands = {
open: createCommand('open folder', async () => { open: createCommand(t('page.edit.command.open'), async () => {
const directory = await window.showDirectoryPicker({ mode: 'readwrite' }); const directory = await window.showDirectoryPicker({ mode: 'readwrite' });
await filesContext.open(directory); await filesContext.open(directory);
}, { key: 'o', modifier: Modifier.Control }), }, { key: 'o', modifier: Modifier.Control }),
close: createCommand('close folder', async () => { close: createCommand(t('page.edit.command.close'), async () => {
filesContext.remove('__root__'); filesContext.remove('__root__');
}), }),
closeTab: createCommand('close tab', async (id: string) => { closeTab: createCommand(t('page.edit.command.closeTab'), async (id: string) => {
filesContext.remove(id); filesContext.remove(id);
}, { key: 'w', modifier: Modifier.Control | (isInstalledPWA ? Modifier.None : Modifier.Alt) }), }, { key: 'w', modifier: Modifier.Control | (isInstalledPWA ? Modifier.None : Modifier.Alt) }),
save: createCommand('save', async () => { save: createCommand(t('page.edit.command.save'), async () => {
await Promise.allSettled(mutatedData().map(async ([file, data]) => { await Promise.allSettled(mutatedData().map(async ([file, data]) => {
// TODO :: add the newly created file to the known files list to that the save file picker is not shown again on subsequent saves // TODO :: add the newly created file to the known files list to that the save file picker is not shown again on subsequent saves
const handle = file.existing ? file.handle : await window.showSaveFilePicker({ suggestedName: file.name, excludeAcceptAllOption: true, types: [{ description: 'JSON file', accept: { 'application/json': ['.json'] } }] }); const handle = file.existing ? file.handle : await window.showSaveFilePicker({ suggestedName: file.name, excludeAcceptAllOption: true, types: [{ description: 'JSON file', accept: { 'application/json': ['.json'] } }] });
@ -257,7 +259,7 @@ const Editor: Component<{ root: FileSystemDirectoryHandle }> = (props) => {
stream.close(); stream.close();
})); }));
}, { key: 's', modifier: Modifier.Control }), }, { key: 's', modifier: Modifier.Control }),
saveAs: createCommand('save as', (handle?: FileSystemFileHandle) => { saveAs: createCommand(t('page.edit.command.saveAs'), (handle?: FileSystemFileHandle) => {
console.log('save as ...', handle); console.log('save as ...', handle);
window.showSaveFilePicker({ window.showSaveFilePicker({
@ -271,13 +273,13 @@ const Editor: Component<{ root: FileSystemDirectoryHandle }> = (props) => {
}); });
}, { key: 's', modifier: Modifier.Control | Modifier.Shift }), }, { key: 's', modifier: Modifier.Control | Modifier.Shift }),
selectAll: createCommand('select all', () => { selectAll: createCommand(t('page.edit.command.selectAll'), () => {
api()?.selectAll(); api()?.selectAll();
}, { key: 'a', modifier: Modifier.Control }), }, { key: 'a', modifier: Modifier.Control }),
clearSelection: createCommand('clear selection', () => { clearSelection: createCommand(t('page.edit.command.clearSelection'), () => {
api()?.clearSelection(); api()?.clearSelection();
}), }),
delete: createCommand('delete selected items', () => { delete: createCommand(t('page.edit.command.delete'), () => {
const { selection, remove } = api() ?? {}; const { selection, remove } = api() ?? {};
if (!selection || !remove) { if (!selection || !remove) {
@ -286,7 +288,7 @@ const Editor: Component<{ root: FileSystemDirectoryHandle }> = (props) => {
remove(selection().map(s => s.key)); remove(selection().map(s => s.key));
}, { key: 'delete', modifier: Modifier.None }), }, { key: 'delete', modifier: Modifier.None }),
inserNewKey: createCommand('insert new key', async () => { insertKey: createCommand(t('page.edit.command.insertKey'), async () => {
const formData = await newKeyPrompt()?.showModal(); const formData = await newKeyPrompt()?.showModal();
const key = formData?.get('key')?.toString(); const key = formData?.get('key')?.toString();
@ -296,7 +298,7 @@ const Editor: Component<{ root: FileSystemDirectoryHandle }> = (props) => {
api()?.addKey(key); api()?.addKey(key);
}), }),
inserNewLanguage: createCommand('insert new language', async () => { insertLanguage: createCommand(t('page.edit.command.insertLanguage'), async () => {
const formData = await newLanguagePrompt()?.showModal(); const formData = await newLanguagePrompt()?.showModal();
const locale = formData?.get('locale')?.toString(); const locale = formData?.get('locale')?.toString();
@ -316,27 +318,27 @@ const Editor: Component<{ root: FileSystemDirectoryHandle }> = (props) => {
}</Context.Menu> }</Context.Menu>
<Menu.Root> <Menu.Root>
<Menu.Item label="file"> <Menu.Item label={t('page.edit.menu.file')}>
<Menu.Item command={commands.open} /> <Menu.Item command={commands.open} />
<Menu.Item command={commands.save} /> <Menu.Item command={commands.close} />
<Menu.Separator /> <Menu.Separator />
<Menu.Item command={commands.close} /> <Menu.Item command={commands.save} />
</Menu.Item> </Menu.Item>
<Menu.Item label="edit"> <Menu.Item label={t('page.edit.menu.edit')}>
<Menu.Item command={commands.inserNewKey} /> <Menu.Item command={commands.insertKey} />
<Menu.Item command={commands.inserNewLanguage} /> <Menu.Item command={commands.insertLanguage} />
<Menu.Separator /> <Menu.Separator />
<Menu.Item command={commands.delete} /> <Menu.Item command={commands.delete} />
</Menu.Item> </Menu.Item>
<Menu.Item label="selection"> <Menu.Item label={t('page.edit.menu.selection')}>
<Menu.Item command={commands.selectAll} /> <Menu.Item command={commands.selectAll} />
<Menu.Item command={commands.clearSelection} /> <Menu.Item command={commands.clearSelection} />

View file

@ -8,11 +8,14 @@
grid: 3em / repeat(5, 3em); grid: 3em / repeat(5, 3em);
} }
& > h1 {
margin-block-end: 0;
}
ul { ul {
display: flex; display: flex;
flex-flow: column; flex-flow: column;
gap: var(--padding-s); gap: var(--padding-s);
padding-inline-start: var(--padding-l); padding-inline-start: var(--padding-l);
margin: 0;
} }
} }

View file

@ -1,19 +1,21 @@
import { A } from "@solidjs/router"; import { A } from "@solidjs/router";
import LandingImage from '../../assets/landing.svg' import LandingImage from '../../assets/landing.svg'
import css from "./welcome.module.css"; import css from "./welcome.module.css";
import { useI18n } from "~/features/i18n";
export default function Welcome() { export default function Welcome() {
const { t } = useI18n();
return <main class={css.main}> return <main class={css.main}>
<LandingImage /> <LandingImage />
<h1>Hi, welcome!</h1> <h1>{t('page.welcome.title')}</h1>
<b>Lets get started</b> <b>{t('page.welcome.subtitle')}</b>
<ul> <ul>
<li><A href="/edit">Start editing</A></li> <li><A href="/edit">{t('page.welcome.edit')}</A></li>
{/* <li><A href="/experimental">Try new features</A></li> */} <li><A href="/instructions">{t('page.welcome.instructions')}</A></li>
<li><A href="/instructions">Read the instructions</A></li> <li><A href="/about">{t('page.welcome.about')}</A></li>
<li><A href="/about">About this app</A></li>
</ul> </ul>
</main>; </main>;
} }

View file

@ -77,8 +77,9 @@
} }
& > dialog { & > dialog {
inset-inline-end: anchor(right); inset-inline-start: anchor(start);
inset-block-start: anchor(bottom); inset-block-start: anchor(end);
position-try-fallbacks: flip-inline;
padding: var(--padding-m); padding: var(--padding-m);
border: none; border: none;