From d1c1b26fe55b88cc5f883f416c6e58af5da27fa5 Mon Sep 17 00:00:00 2001 From: Nils Lindemann Date: Wed, 3 Sep 2025 15:40:40 +0200 Subject: [PATCH] Improve abbr handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After these changes it now seems to handle descriptions in title attributes well, both when translating a document the first time – see the abbr section in the `ru/docs/_llm-test.md` which I committed for reference, but I am not sure if everything is correct there, as I do not speak Russian – and when updating translations – tested with e.g. `ru/docs/features.md` and `ru/docs/tutorial/path-params-numeric-validations.md`, not committed. I simplified rule 3 to just match when the separator is a colon (`:`), not when it is a comma (`,`), there are otherwise too many cases it may misunderstand, as commas are regularly used in title attributes. Updated the two instances in the English docs (`features.md` and `tutorial\sql-databases.md`) where a comma was used instead of a colon in a case, which we match with rule 3. I fixed the results in schemes they accidentally had `(de)` appended, but they are language independent. --- docs/de/docs/_llm-test.md | 21 ++- docs/en/docs/_llm-test.md | 21 ++- docs/en/docs/features.md | 2 +- docs/en/docs/tutorial/sql-databases.md | 2 +- docs/ru/docs/_llm-test.md | 241 +++++++++++++++++++++++++ docs/ru/llm-prompt.md | 5 + scripts/translate.py | 97 +++++----- 7 files changed, 341 insertions(+), 48 deletions(-) create mode 100644 docs/ru/docs/_llm-test.md create mode 100644 docs/ru/llm-prompt.md diff --git a/docs/de/docs/_llm-test.md b/docs/de/docs/_llm-test.md index b6b6a0f42..ba45d6623 100644 --- a/docs/de/docs/_llm-test.md +++ b/docs/de/docs/_llm-test.md @@ -113,9 +113,26 @@ Etwas Text [Interner Link](foo.md#bar){.internal-link target=_blank} -## Abbr-Elemente { #abbr-elements } +## HTML-„abbr“-Elemente { #html-abbr-elements } -Hier einige Dinge, die in `abbr`-Elemente gehüllt sind (einige sind erfunden): GTD, XWT, PSGI, Cluster, Deep Learning, MDN. +Hier einige Dinge, die in HTML-„abbr“-Elemente gewrappt sind (einige sind erfunden): + +### Ganze Phrase { #full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### Erklärung { #explanation } + +* Cluster +* Deep Learning + +### Ganze Phrase: Erklärung { #full-phrase-explanation } + +* MDN +* I/O. ## Überschriften { #headings } diff --git a/docs/en/docs/_llm-test.md b/docs/en/docs/_llm-test.md index 0c3782fb3..36db73c50 100644 --- a/docs/en/docs/_llm-test.md +++ b/docs/en/docs/_llm-test.md @@ -113,9 +113,26 @@ Some text [Internal link](foo.md#bar){.internal-link target=_blank} -## Abbr elements { #abbr-elements } +## HTML "abbr" elements { #html-abbr-elements } -Here some things wrapped in `abbr` elements (Some are invented): GTD, XWT, PSGI, cluster, Deep Learning, MDN. +Here some things wrapped in HTML "abbr" elements (Some are invented): + +### Full phrase { #full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### Explanation { #explanation } + +* cluster +* Deep Learning + +### Full phrase: Explanation { #full-phrase-explanation } + +* MDN +* I/O. ## Headings { #headings } diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md index 681caac35..d44d7a6ac 100644 --- a/docs/en/docs/features.md +++ b/docs/en/docs/features.md @@ -190,7 +190,7 @@ With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on * **No brainfuck**: * No new schema definition micro-language to learn. * If you know Python types you know how to use Pydantic. -* Plays nicely with your **IDE/linter/brain**: +* Plays nicely with your **IDE/linter/brain**: * Because pydantic data structures are just instances of classes you define; auto-completion, linting, mypy and your intuition should all work properly with your validated data. * Validate **complex structures**: * Use of hierarchical Pydantic models, Python `typing`’s `List` and `Dict`, etc. diff --git a/docs/en/docs/tutorial/sql-databases.md b/docs/en/docs/tutorial/sql-databases.md index 79538e566..cfa1c9073 100644 --- a/docs/en/docs/tutorial/sql-databases.md +++ b/docs/en/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ Here we'll see an example using "ORMs"), FastAPI doesn't force you to use anything. 😎 +You could use any other SQL or NoSQL database library you want (in some cases called "ORMs"), FastAPI doesn't force you to use anything. 😎 /// diff --git a/docs/ru/docs/_llm-test.md b/docs/ru/docs/_llm-test.md new file mode 100644 index 000000000..622a359a7 --- /dev/null +++ b/docs/ru/docs/_llm-test.md @@ -0,0 +1,241 @@ +# Тест LLM { #llm-test } + +Этот документ проверяет, понимает ли LLM инструкции, заданные в общем промпте в `scripts/translate.py`, и инструкции в языковом промпте `docs/{language code}/llm-prompt.md` (которые добавляются к инструкциям в общем промпте). + +Использование: + +* Сделайте свежий перевод этого документа на нужный целевой язык. +* Проверьте, что в целом всё в порядке. +* Если что‑то не так, но это можно исправить улучшением английского документа или общего/языкового промпта, сделайте это. +* Затем вручную исправьте оставшиеся проблемы в переводе, чтобы получился хороший перевод. +* Повторно переведите, используя существующий, хороший перевод. Идеальный результат — LLM ничего не меняет. Это означало бы, что общий промпт и языковой промпт настолько хороши, насколько это возможно (Неожиданный поворот: обычно он всё же внесёт несколько на вид случайных правок, вероятно потому, что LLM — не детерминированные алгоритмы). + +Идея в том, что при работе над переводом для конкретного языка (если есть возможность запускать `scripts/translate.py`) добавлять сюда примеры найденных частных случаев (не подробный список, лишь примеры таких случаев) и тестировать на этом документе, а не на каждом отдельном документе, переводя его многократно, что стоит по нескольку центов за перевод. Кроме того, добавляя такие частные случаи сюда, другие проекты перевода тоже узнают о них. + +## Фрагменты кода { #code-snippets} + +Это фрагмент кода: `foo`. А это ещё один фрагмент кода: `bar`. И ещё один: `baz quux`. + +## Кавычки { #quotes } + +Вчера мой друг написал: "Если вы правильно напишете слово 'incorrectly', вы напишете его неправильно". На что я ответил: "Верно, но 'incorrectly' — это неправильно, а не '"incorrectly"'". + +## Кавычки во фрагментах кода { #quotes-in-code-snippets} + +`pip install "foo[bar]"` + +Примеры строковых литералов во фрагментах кода: `"this"`, `'that'`. + +Сложный пример строковых литералов во фрагментах кода: `f"I like {'oranges' if orange else "apples"}"` + +Хардкор: `Yesterday my friend wrote: "If you spell incorrectly correctly you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'!"` + +## Блоки кода { #code-blocks } + +Пример кода Bash... + +```bash +# Напечатать приветствие вселенной +echo "Hello universe" +``` + +...и пример кода консоли... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...и ещё один пример кода консоли... + +```console +// Создайте каталог "Code" +$ mkdir code +// Перейдите в этот каталог +$ cd code +``` + +...и пример кода на Python... + +```Python +wont_work() # Это не сработает 😱 +works(foo="bar") # Это сработает 🎉 +``` + +...и на этом всё. + +## Вкладки и цветные блоки { #tabs-and-colored-boxes } + +//// tab | Это вкладка + +/// info | Информация +Немного текста +/// + +/// note | Примечание +Немного текста +/// + +/// note | Технические детали +Немного текста +/// + +/// check | Проверка +Немного текста +/// + +/// tip | Совет +Немного текста +/// + +/// warning | Предупреждение +Немного текста +/// + +/// danger | Опасность +Немного текста +/// + +//// + +## Веб‑ и внутренние ссылки { #web-and-internal-links } + +[Ссылка на заголовок выше](#code-snippets) + +Внешняя ссылка + +Ссылка FastAPI + +Ссылка на стиль +Ссылка на скрипт +Ссылка на изображение + +[Внутренняя ссылка](foo.md#bar){.internal-link target=_blank} + +## Элементы HTML "abbr" { #html-abbr-elements } + +Здесь некоторые вещи, обёрнутые в элементы HTML "abbr" (некоторые вымышленные): + +### Полная фраза { #full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### Объяснение { #explanation } + +* кластер +* Глубокое обучение + +### Полная фраза: Объяснение { #full-phrase-explanation } + +* MDN +* I/O. + +## Заголовки { #headings } + +### Разработка веб‑приложения — учебник { #develop-a-webapp-a-tutorial } + +Здравствуйте. + +### Подсказки типов и аннотации { #type-hints-and-annotations } + +Ещё раз здравствуйте. + +### Супер‑ и подклассы { #super-and-subclasses } + +Ещё раз здравствуйте. + +## Предложения с предпочтительными переводами, (возможно) заданными в языковом промпте { #sentences-with-preferred-translations-maybe-defined-in-the-language-prompt } + +Добро пожаловать. +Я восхищаюсь вашим пуловером. +Ей нравятся фрукты, например, яблоки. +Ему нравятся апельсины, бананы и т. д. +Читайте документацию. +Прочтите учебник — Руководство пользователя. +Затем прочтите Руководство для продвинутых пользователей. +Если эта переменная окружения существует, сделайте что‑нибудь. +Прочитайте переменную окружения `PATH`. +Это то же самое, что `PATH`. +Установите из `requirements.txt`. +Используйте APIRouter. +Запустите приложение. +Создайте приложение. +Это заголовок Authorization. +Это заголовок `Authorization`. +Ожидание фоновой задачи. +Нажмите кнопку. +Попробуйте этого облачного провайдера. +Используйте CLI. +То есть интерфейс командной строки. +Значение по умолчанию — "foo". +Объявление по умолчанию — "bar". +Словари, или dict, — полезные структуры данных. +Перечисления, или Enum, тоже имеют своё применение. +Движок сделает это. +Верните ответ с ошибкой. +Дождитесь события. +Бросьте исключение. +Обработчик исключений обработает это. +Определение модели формы. +Отправка тела формы. +Доступ к заголовку. +Изменение заголовков. +Написание в заголовках. +Пересылаемые заголовки часто используются в связке с прокси‑серверами. +Прослушивание события жизненного цикла. +Блокировка означает, что мы «захватываем» ресурс, чтобы безопасно его изменить. +Разработка мобильного приложения. +Определение объекта модели. +Что‑то ждёт монтирования. +Теперь это смонтировано. +Другой источник. +У нас есть переопределение для этого. +У функции один параметр. +Параметр функции — int. +У функции много параметров. +Параметр по умолчанию — bool. +Параметр body содержит тело запроса. +Также называется параметром тела запроса. +Параметр path содержит переменную в пути запроса. +Параметр query содержит параметры строки запроса в пути запроса. +Параметр cookie содержит куки запроса. +Параметр header содержит заголовки запроса. +Параметр form содержит поля формы запроса. +Полезная нагрузка — это запрос/ответ без метаданных. +Этот запрос запрашивает элементы старше недели. +Итог: всё гладко. +Запрос получен. +Получение тела запроса. +Получение тел запросов. +Возврат ответа. +То, что возвращает функция, имеет возвращаемое значение. +И тип возвращаемого значения. +Мы слушаем события запуска и остановки. +Мы ждём запуска сервера. +Подробности описаны в документации SQLModel. +Используйте SDK. +Тег `Horst` означает, что Хорст должен это сделать. +У этого параметра есть аннотация типа. +То есть подсказка типа. +Подстановочный символ — `*`. +Класс worker делает то и это. +Рабочий процесс тоже что‑то делает. +Я закоммичу это завтра. +Вчера я изменил код. +Давайте запустим наше приложение. +Давайте отдадим эту страницу. +Прежде чем делать это, обновите FastAPI. +Это обёрнуто в HTML‑тег. +`foo` как `int`. +`bar` как `str`. +`baz` как `list`. +Документация FastAPI. +Производительность Starlette. +`foo` чувствителен к регистру. +"Bar" не чувствителен к регистру. +Стандартные классы Python. +Это устарело. diff --git a/docs/ru/llm-prompt.md b/docs/ru/llm-prompt.md new file mode 100644 index 000000000..3ec1ccdc8 --- /dev/null +++ b/docs/ru/llm-prompt.md @@ -0,0 +1,5 @@ +### Target language + +Translate to Russian (русский язык). + +Language code: ru. diff --git a/scripts/translate.py b/scripts/translate.py index c678b6e05..5962a1195 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -508,9 +508,19 @@ Example: ### HTML abbr elements -Translate HTML abbr elements as follows: +Translate HTML abbr elements («text») as follows: -1) If the title attribute gives the full phrase for an abbreviation, then keep the phrase, append a dash («–»), followed by the translation of the phrase. +1) If the text surrounded by the abbr element is an abbreviation (the text may be surrounded by further HTML or Markdown markup or quotes, for example «text» or «`text`» or «"text"», ignore that further markup when deciding if the text is an abbreviation), and if the description (the text inside the title attribute) contains the full phrase for this abbreviation, then append a dash («–») to the full phrase, followed by the translation of the full phrase. + +Conversion scheme: + + Source (English): + + {abbreviation} + + Result: + + {abbreviation} Examples: @@ -530,17 +540,17 @@ Examples: TL;DR: »»» -Conversion scheme title attribute: +1.1) If the language to which you translate mostly uses the letters of the ASCII char set (for example Spanish, French, German, but not Russian, Chinese) and if the translation of the full phrase is identical to, or starts with the same letters as the original full phrase, then only give the translation of the full phrase. + +Conversion scheme: Source (English): - {full phrase} + {abbreviation} - Result (German): - - {full phrase} – {translation of full phrase} + Result: -1.1) If the translation of the phrase starts with the same letters, then just use the translation. + {abbreviation} Examples: @@ -548,7 +558,7 @@ Examples: ««« JWT - `Enum` + Enum ASGI »»» @@ -556,21 +566,21 @@ Examples: ««« JWT - `Enum` + Enum ASGI »»» -Conversion scheme title attribute: +2) If the description is not a full phrase for an abbreviation which the abbr element surrounds, but some other information, then just translate the description. - Source (English): +Conversion scheme: - {full phrase} + Source (English): - Result (German): + {text} - {translation of full phrase} + Result: -2) If the title attribute explains something in its own words, then translate it, if possible. + {translation of text} Examples: @@ -578,8 +588,8 @@ Examples: ««« path - linter - "parsing" + linter + parsing 0.95.0 at the time of writing this »»» @@ -589,22 +599,23 @@ Examples: ««« Pfad Linter - „Parsen“ + Parsen 0.95.0 zum Zeitpunkt als das hier geschrieben wurde »»» -Conversion scheme title attribute: - Source (English): +3) If the text surrounded by the abbr element is an abbreviation and the description contains both the full phrase for that abbreviation, and other information, separated by a colon («:»), then append a dash («–») and the translation of the full phrase to the original full phrase and translate the other information. - {explanation} +Conversion scheme: - Result (German): + Source (English): + + {abbreviation} - {translation of explanation} + Result: -3) If the title attribute gives the full phrase for an abbreviation, followed by a colon («:») or a comma («,»), followed by an explanation, then keep the phrase, append a dash («–»), followed by the translation of the phrase, followed by a colon («:»), followed by the translation of the explanation. + {abbreviation} Examples: @@ -612,9 +623,8 @@ Examples: ««« I/O - CDN - IDE - "ORMs" + CDN + IDE »»» Result (German): @@ -623,34 +633,37 @@ Examples: I/O CDN IDE - „ORMs“ »»» -Conversion scheme title attribute: - - Source (English): - - {full phrase}: {explanation} +3.1) Like in rule 2.1, you can leave the original full phrase away, if the translated full phrase is identical or starts with the same letters as the original full phrase. - OR +Conversion scheme: Source (English): - {full phrase}, {explanation} + {abbreviation} - Result (German): + Result: - {full phrase} – {translation of full phrase}: {translation of explanation} + {abbreviation} -3.1) For the full phrase (the part before the dash in the translation) rule 1.1 also applies, speak, you can leave the original full phrase away and just use the translated full phrase, if it starts with the same letters. The result becomes: +Example: + + Source (English): -Conversion scheme title attribute: + ««« + ORM + »»» Result (German): - {translation of full phrase}: {translation of explanation} + ««« + ORM + »»» + +4) Apply above rules also when there is an existing translation! Make sure that all title attributes in abbr elements get properly translated or updated, using the schemes given above. -4) If there is an HTML abbr element in a sentence in an existing translation, but that element does not exist in the related sentence in the English text, then keep that HTML abbr element in the translation, do not change or remove it. Except when you remove the whole sentence from the translation, because the whole sentence was removed from the English text. The reasoning for this rule is, that such abbr elements are manually added by the human editor of the translation, in order to translate or explain an English word to the human readers of the translation. They would not make sense in the English text, but they do make sense in the translation. So keep them in the translation, even though they are not part of the English text. This rule only applies to HTML abbr elements. +5) If there is an existing translation, and it has ADDITIONAL abbr elements in a sentence, and these additional abbr elements do not exist in the related sentence in the English text, then KEEP those additional abbr elements in the translation. Do not remove them. Except when you remove the whole sentence from the translation, because the whole sentence was removed from the English text, then also remove the abbr element. The reasoning for this rule is, that such additional abbr elements are manually added by the human editor of the translation, in order to translate or explain an English word to the human readers of the translation. These additional abbr elements would not make sense in the English text, but they do make sense in the translation. So keep them in the translation, even though they are not part of the English text. This rule only applies to abbr elements. """