Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(translate): improve prompts to better support i18n suffixes #7167

Merged
merged 2 commits into from
Mar 25, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/hungry-terms-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@logto/translate": patch
---

improve openai prompt to better support i18n plural form suffixes
38 changes: 35 additions & 3 deletions packages/translate/src/prompts.ts
Original file line number Diff line number Diff line change
@@ -22,9 +22,41 @@ export const getTranslationPromptMessages = ({
}: GetTranslationPromptProperties) => [
{
role: 'assistant',
content: `You are a assistant translator and will receive a TypeScript object. Traverse and find object values with "${untranslatedMark}" annotation on the top, then translate these values to target locale "${targetLanguage}". Remove the "${untranslatedMark}" annotations from output. Escape the single quotes (if any) in translated results by prepending a backslash. Keep the interpolation double curly brackets and their inner values intact. Make sure there is a space between the CJK and non-CJK characters. Prefer using "你" instead of "您" in Chinese. Do not include sample code snippet below in the final output. ${conditionalString(
extraPrompt
)}
content: `
You are a assistant translator and will receive a TypeScript object.
Traverse and find object values with "${untranslatedMark}" annotation on the top,
then translate these values to target locale "${targetLanguage}".
Remove the "${untranslatedMark}" annotations from output.
Escape the single quotes (if any) in translated results by prepending a backslash.
Keep the interpolation double curly brackets and their inner values intact.
Make sure there is a space between the CJK and non-CJK characters.
Prefer using "你" instead of "您" in Chinese.
Do not include sample code snippet below in the final output.
When translating phrases whose keys have plural suffixes, pay attention to the plural rules of the target language.
For example, the plural suffixes in English are "_one" and "_other". But other languages may have additional suffixes like "_two", "_few" and "_many".
These suffixed phrases always have a "{{count}}" variable. When translating these phrases, you need to imagine the variable is replaced with the number indicated by the suffix, and use proper plural forms in the final translation.
For example, you may meet these phrases in English:
\`\`\`ts
const password_requirement = {
length_one: 'requires a minimum of {{count}} character',
length_two: 'requires a minimum of {{count}} characters',
length_few: 'requires a minimum of {{count}} characters',
length_many: 'requires a minimum of {{count}} characters',
length_other: 'requires a minimum of {{count}} characters',
};
\`\`\`
And the proper translation in Russian would be:
\`\`\`ts
const password_requirement = {
length_one: 'Требуется минимум {{count}} символ',
length_two: 'Требуется минимум {{count}} символа',
length_few: 'Требуется минимум {{count}} символа',
length_many: 'Требуется минимум {{count}} символов',
length_other: 'Требуется минимум {{count}} символов',
};
\`\`\`

${conditionalString(extraPrompt)}

Take translating to zh-CN as an example, if the input is:
\`\`\`ts

Unchanged files with check annotations Beta

###### [STAGE] Build ######
FROM node:20-alpine as builder

Check warning on line 2 in Dockerfile

GitHub Actions / main-dockerize

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
WORKDIR /etc/logto
ENV CI=true
RUN rm -rf .scripts pnpm-*.yaml packages/cloud
###### [STAGE] Seal ######
FROM node:20-alpine as app

Check warning on line 41 in Dockerfile

GitHub Actions / main-dockerize

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
WORKDIR /etc/logto
COPY --from=builder /etc/logto .
RUN mkdir -p /etc/logto/packages/cli/alteration-scripts && chmod g+w /etc/logto/packages/cli/alteration-scripts