Skip to content

Commit 1d99ec4

Browse files
committed
Add multilanguage support using Wuchale
1 parent ac1db77 commit 1d99ec4

40 files changed

+12531
-92
lines changed

CONTRIBUTING.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ Same goes for feature requests.
77
PR's are welcome, too!
88
Note that opening a PR means agreeing that your code becomes distributed under the MIT license.
99

10-
If you want to share some thoughts on the Atomic Data _specification_, please [drop an issue in the Atomic Data docs repo](https://github.com/ontola/atomic-data/issues).
10+
If you want to share some thoughts on the Atomic Data _specification_, please [drop an issue in the Atomic Data repo](https://github.com/atomicdata-dev/atomic-server/issues).
1111
Check out the [Roadmap](https://docs.atomicdata.dev/roadmap.html) if you want to learn more about our plans and the history of the project.
1212

1313
## Table of contents
1414

1515
- [Table of contents](#table-of-contents)
16+
- [Translation \& Internationalization](#translation--internationalization)
1617
- [Running \& compiling](#running--compiling)
1718
- [Running locally (with local development browser)](#running-locally-with-local-development-browser)
1819
- [IDE setup (VSCode)](#ide-setup-vscode)
@@ -39,6 +40,11 @@ Check out the [Roadmap](https://docs.atomicdata.dev/roadmap.html) if you want to
3940
- [Deploying to atomicdata.dev](#deploying-to-atomicdatadev)
4041
- [Publishing atomic-cli to WAPM](#publishing-atomic-cli-to-wapm)
4142

43+
## Translation & Internationalization
44+
45+
AtomicServer supports a small number of languages.
46+
Most of these translations are done by AI and might contain mistakes, if you notice any feel free to [open an issue](https://github.com/atomicdata-dev/atomic-server/issues).
47+
4248
## Running & compiling
4349

4450
TL;DR Clone the repo and run `cargo run` from each folder (e.g. `cli` or `server`).
@@ -124,7 +130,7 @@ cargo nextest run test_name_substring
124130
# First, run the server
125131
cargo run
126132
# now, open new terminal window
127-
cd server/e2e_tests/ && npm i && npm run test
133+
cd browser && pnpm i && pnpm test-e2e
128134
# if things go wrong, debug!
129135
pnpm run test-query {testname}
130136
```

browser/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This changelog covers all five packages, as they are (for now) updated as a whol
1919
- [#1008](https://github.com/atomicdata-dev/atomic-server/issues/1008) Add info dropdowns to different sections of the ontology editor for more information about the section.
2020
- [#459](https://github.com/atomicdata-dev/atomic-server/issues/459) New feature: Add tags to your resources to better organize your data. Search for resources with specific tags in the search bar with `tag:[name]`.
2121
- [#951](https://github.com/atomicdata-dev/atomic-server/issues/951) New feature: Atomic Assistant, AI chat interface with support for custom agents, MCP servers and more. Bring your own OpenRouter key or use Ollama to host your own models.
22+
- [#1118](https://github.com/atomicdata-dev/atomic-server/issues/1118) New feature: AtomicServer is now also available in German, Spanish and French. Change your language on the settings page.
2223

2324
### @tomic/lib
2425

browser/CONTRIBUTING.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,12 @@ Vite hosts the data-browser and targets `.ts` files which enables hot reload / h
3838
If you're editing `@tomic/lib` or `@tomic/react`, you need to re-build the library, as `atomic-data-browser` imports the `.js` files.
3939
You can auto re-build using the `watch` commands in `@tomic/lib` and `@tomic/react`.
4040
If you run `pnpm start` from the root, these will be run automatically.
41-
Note that you may need to refresh your screen manually to show updates from these libraries.
4241

43-
There are two possible solutions for improving this workflow:
42+
## Localization
4443

45-
- In `package.json` of the libraries, set the `main` to `src/index.ts` (the typescript file). However, make sure to _not_ publish this to npm, as many clients will fail.
46-
- Properly set up aliases with vite. I've tried this before, but failed.
44+
Atomic Data Browser uses [Wuchale](https://wuchale.dev/) for localization.
45+
When adding new text to the app wuchale will automatically extract it and add it to the locale files (When running the vite dev server).
46+
Make sure you provide translations for the any new text you add.
47+
To help with this you can provide a Google Gemini API key, Wuchale will then use this to generate translations for you automatically.
48+
To do so export the key in your terminal or use something like direnv to set the key: `export GEMINI_API_KEY=your_api_key`
49+
More info: [How to use Gemini live translation](https://wuchale.dev/guides/gemini/)

browser/data-browser/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
"stylis": "4.3.0",
6565
"tippy.js": "^6.3.7",
6666
"tiptap-markdown": "^0.8.10",
67+
"wuchale": "^0.16.5",
68+
"@wuchale/jsx": "^0.7.4",
69+
"@wuchale/vite-plugin": "^0.14.6",
6770
"zod": "^4.1.5"
6871
},
6972
"devDependencies": {
@@ -105,6 +108,7 @@
105108
"preview": "vite preview",
106109
"start": "vite",
107110
"test": "vitest run",
108-
"typecheck": "pnpm exec tsc --noEmit"
111+
"typecheck": "pnpm exec tsc --noEmit",
112+
"clean-translations": "pnpm exec wuchale --clean"
109113
}
110114
}

browser/data-browser/src/Providers.tsx

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { NavStateProvider } from './components/NavState';
2020
import { Toaster } from './components/Toaster';
2121
import { McpServersProvider } from './components/AI/MCP/useMcpServers';
2222
import { AISettingsContextProvider } from '@components/AI/AISettingsContext';
23+
import { LocaleProvider } from '@components/LocaleContext';
2324

2425
// Setup bugsnag for error handling, but only if there's an API key
2526
const ErrBoundary = window.bugsnagApiKey
@@ -45,43 +46,45 @@ const shouldForwardProp: ShouldForwardProp<'web'> = (propName, target) => {
4546
export const Providers: React.FC<React.PropsWithChildren> = ({ children }) => {
4647
return (
4748
<NavStateProvider>
48-
<AppSettingsContextProvider>
49-
<AISettingsContextProvider>
50-
<McpServersProvider>
51-
<ControlLockProvider>
52-
<HotKeysWrapper>
53-
<StyleSheetManager shouldForwardProp={shouldForwardProp}>
54-
<ThemeWrapper>
55-
<GlobalStyle />
56-
<ErrBoundary FallbackComponent={CrashPage}>
57-
{/* Default form validation provider. Does not do anything on its own but will make sure useValidation works without context*/}
58-
<FormValidationContextProvider
59-
onValidationChange={() => undefined}
60-
>
61-
<Toaster />
62-
<MetaSetter />
63-
<DropdownContainer>
64-
<DialogGlobalContextProvider>
65-
<PopoverContainer>
66-
<DropdownContainer>
67-
<NewResourceUIProvider>
68-
<SkipNav />
69-
<NavWrapper>{children}</NavWrapper>
70-
</NewResourceUIProvider>
71-
</DropdownContainer>
72-
</PopoverContainer>
73-
<NetworkIndicator />
74-
</DialogGlobalContextProvider>
75-
</DropdownContainer>
76-
</FormValidationContextProvider>
77-
</ErrBoundary>
78-
</ThemeWrapper>
79-
</StyleSheetManager>
80-
</HotKeysWrapper>
81-
</ControlLockProvider>
82-
</McpServersProvider>
83-
</AISettingsContextProvider>
84-
</AppSettingsContextProvider>
49+
<LocaleProvider>
50+
<AppSettingsContextProvider>
51+
<AISettingsContextProvider>
52+
<McpServersProvider>
53+
<ControlLockProvider>
54+
<HotKeysWrapper>
55+
<StyleSheetManager shouldForwardProp={shouldForwardProp}>
56+
<ThemeWrapper>
57+
<GlobalStyle />
58+
<ErrBoundary FallbackComponent={CrashPage}>
59+
{/* Default form validation provider. Does not do anything on its own but will make sure useValidation works without context*/}
60+
<FormValidationContextProvider
61+
onValidationChange={() => undefined}
62+
>
63+
<Toaster />
64+
<MetaSetter />
65+
<DropdownContainer>
66+
<DialogGlobalContextProvider>
67+
<PopoverContainer>
68+
<DropdownContainer>
69+
<NewResourceUIProvider>
70+
<SkipNav />
71+
<NavWrapper>{children}</NavWrapper>
72+
</NewResourceUIProvider>
73+
</DropdownContainer>
74+
</PopoverContainer>
75+
<NetworkIndicator />
76+
</DialogGlobalContextProvider>
77+
</DropdownContainer>
78+
</FormValidationContextProvider>
79+
</ErrBoundary>
80+
</ThemeWrapper>
81+
</StyleSheetManager>
82+
</HotKeysWrapper>
83+
</ControlLockProvider>
84+
</McpServersProvider>
85+
</AISettingsContextProvider>
86+
</AppSettingsContextProvider>
87+
</LocaleProvider>
8588
</NavStateProvider>
8689
);
8790
};

browser/data-browser/src/chunks/AI/AgentConfig.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const defaultAgents: AIAgent[] = [
5959
id: 'dev.atomicdata.atomic-agent',
6060
description:
6161
"An agent that is specialized in helping you use AtomicServer. It takes context from what you're doing.",
62-
systemPrompt: `You are an AI assistant in the Atomic Data Browser. Users will ask questions about their data and you will answer by looking at the data or using your own knowledge about the world.
62+
systemPrompt: /* wc-ignore */ `You are an AI assistant in the Atomic Data Browser. Users will ask questions about their data and you will answer by looking at the data or using your own knowledge about the world.
6363
Atomic Data uses JSON-AD, Every resource including the properties themselves have a subject (the '@id' property in the JSON-AD), this is a URL that points to the resource.
6464
Resources are always referenced by subject so make sure you have all the subjects you need before editing or creating resources.
6565

browser/data-browser/src/chunks/AI/atomicSchemaHelpers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// @wc-ignore-file
12
import { type Core, type Store } from '@tomic/react';
23

34
export const toClassString = async (subject: string, store: Store) => {

browser/data-browser/src/chunks/AI/useAgentAutoSelect.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const useAutoAgentSelect = () => {
1515

1616
const getModel = useGetModel();
1717

18-
const basePrompt = `You are part of an AI Chat application. It is your job to determine what agent to use to answer the users question.
18+
const basePrompt = /* @wc-ignore */ `You are part of an AI Chat application. It is your job to determine what agent to use to answer the users question.
1919
These are the agents you can choose from:
2020
2121
${agents.map(agent => agentToText(agent, mcpServers)).join('\n')}
@@ -35,8 +35,8 @@ User question: `;
3535

3636
const { object } = await generateObject({
3737
model,
38-
schemaName: 'Agent',
39-
schemaDescription: 'The agent to use for the question.',
38+
schemaName: /* @wc-ignore */ 'Agent',
39+
schemaDescription: /* @wc-ignore */ 'The agent to use for the question.',
4040
schema: z.object({
4141
agentId: z.string(),
4242
}),

browser/data-browser/src/chunks/AI/useAtomicTools.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// @wc-ignore-file
12
import {
23
commits,
34
core,

browser/data-browser/src/chunks/AI/useGenerativeData.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// @wc-ignore-file
12
import { generateObject, generateText } from 'ai';
23
import { type AtomicUIMessage } from './types';
34
import z from 'zod';

0 commit comments

Comments
 (0)