Skip to main content

Noctalia i18n Core

简体中文

Noctalia i18n Core is a read-only Python client for project progress, current translations, and changes from Noctalia Translate. Storage, scheduling, delivery, and application policy belong to the caller.

Core capabilities

  • Read project details, translation context, and project-wide and per-locale progress.
  • Read current translations as a complete catalog, exact-key results, or text-search results.
  • Query missing keys and translations that need review in a selected locale.
  • List dot-separated translation keys and filter them by hierarchy prefix.
  • Read complete changes for selected keys in one locale.
  • Lazily read the project-wide change stream with locale, time, and anchor boundaries.
  • Use a caller-owned requests.Session when connection policy must be configured by the application.

Project structure

noctalia_i18n_core/
├── client.py   # Website requests and response validation
└── models.py   # Normalized project and change values

Installation

uv add noctalia-i18n-core

Or with pip:

pip install noctalia-i18n-core

Usage

Create a client

from noctalia_i18n_core import NoctaliaClient

with NoctaliaClient("noctalia", timeout=30) as client:
    key = "settings.widgets.settings.scroll-repeat.label"
    value = client.translations(key, locales=("zh-Hans",))[key]["zh-Hans"]
    changes = client.changes(key, locale="zh-Hans")

    print(value)
    print(changes[0].occurred_at if changes else "No changes")

The client closes only the session it creates. Pass a configured requests.Session when the application owns connection settings such as proxies or retries.

Project details and progress

project() makes one project request and returns the public name, description, translation context, and current progress. Project and locale progress use the integer percentage shown by the website. The review count identifies translations whose English source changed after that translation was last saved.

project = client.project()

print(project.name, project.key_count, project.language_count, project.progress)
for locale in project.locales:
    print(
        locale.code,
        locale.progress,
        locale.missing_count,
        locale.review_count,
    )

Current translations

translations() reads one or more exact keys in one batch request. Its key-first result preserves the requested key and locale order. A requested key remains present with an empty mapping when no selected locale has a value.

values = client.translations(
    "settings.widgets.settings.scroll-repeat.description",
    "settings.widgets.settings.scroll-repeat.label",
    locales=("zh-Hans", "en"),
)

catalog() makes one complete export request and returns {key: {locale: value}}. It is intended for callers that need every current translation.

catalog = client.catalog()
source_text = catalog["settings.widgets.settings.scroll-repeat.description"]["en"]

Text search

search_translations() searches the key and current value in search_locale, follows all result pages, and reads the requested result locales for the matching keys. If locales is omitted, the result contains only search_locale.

matches = client.search_translations(
    "确认",
    search_locale="zh-Hans",
    locales=("zh-Hans", "en"),
)

Missing translations and reviews

missing_keys() returns keys without a current translation in one locale. reviews() returns translations whose English source changed after the translation was last saved, including the previous and current English source. Both queries accept query to filter their results.

missing = client.missing_keys("fr", query="scroll")
reviews = client.reviews("fr")

for review in reviews:
    print(review.key, review.old_source, review.new_source)

Translation keys

keys() makes one key-tree request and returns the complete key list. A prefix matches a complete dot-separated hierarchy rather than an arbitrary string prefix.

widget_keys = client.keys(prefix="settings.widgets")

Changes for selected keys

changes() reads the complete changes for one or more exact keys in one locale. The returned tuple is ordered from newest to oldest; multiple key results are merged in that order.

changes = client.changes(
    "settings.widgets.settings.scroll-repeat.description",
    locale="zh-Hans",
)
for change in changes:
    print(change.occurred_at, change.action, change.new_value)

Project change stream

iter_changes() lazily reads the project-wide change stream in the order supplied by the website. since and until are inclusive, timezone-aware boundaries and are normalized to UTC. locale restricts the stream to one locale.

from datetime import UTC, datetime

recent = client.iter_changes(
    locale="zh-Hans",
    since=datetime(2026, 8, 1, tzinfo=UTC),
)
for change in recent:
    print(change.key, change.action)

after is a website change ID. The client confirms the anchor before yielding a result and raises RuntimeError when it is absent. on_progress receives the completed page number and current total page count after each request.

API reference

NoctaliaClient

NoctaliaClient(project, *, timeout, session=None)

project is the website project identifier. timeout is a positive finite number of seconds. session may be a caller-owned requests.Session; the client closes it only when it created the session itself.

Member Result
slug The project identifier passed to the constructor
project() Project details and current translation progress
keys(*, prefix=None) tuple[str, ...] of complete or prefix-matched keys
catalog() dict[str, dict[str, str]] containing the complete current catalog
translations(key, *keys, locales=None) Key-first exact translations
search_translations(query, *, search_locale, locales=None) Key-first translations for text matches
missing_keys(locale, *, query=None) Missing translation keys in one locale
reviews(locale, *, query=None) Translations needing review in one locale
changes(key, *keys, locale) Newest-first exact-key changes
iter_changes(*, locale=None, since=None, until=None, after=None, on_progress=None) Lazy project-wide change iterator
close() Closes an owned HTTP session

translations() and changes() require at least one positional key. translations() returns requested keys even when their result is empty. changes() returns a tuple and requests each selected key from the website. iter_changes() never accepts keys and remains lazy until iteration begins.

Invalid arguments raise ValueError. Network failures and responses that do not match the website contract raise RuntimeError.

Project and Locale

Project contains public project details and progress aggregated from the current locale states:

Field or property Description
slug Website project identifier
name Project name
description Project description, or None when absent
translation_context Translation guidance and terminology, or None when absent
key_count Current translation key count
locales Website-ordered tuple[Locale, ...]
language_count Configured locale count
translation_count Current translation count
missing_count Current missing translation count
review_count Current translations that need review
progress Integer completion percentage shown by the website

Each Locale contains code, translation_count, missing_count, review_count, and the derived progress. Locales without any current translations remain present in the project result.

Review

Each review contains key, locale, old_source, new_source, and translation_url. old_source is None when no previous source text exists. The source difference comes from the website's Needs review query and is distinct from changes to the translation itself.

Change

Each change has the following fields:

Field Description
id Website change identifier
key Translation key
locale Locale changed by the record
action added, modified, or deleted
old_value Previous text, or None for an addition
new_value New text, or None for a deletion
occurred_at UTC-aware datetime
translation_url Translation page for the key and locale
actor_login Contributor login, or None for an automated change
actor_url Contributor profile URL, when available
actor_avatar_url Contributor avatar URL, when available

ChangeAction is the literal type "added" | "modified" | "deleted". SOURCE_LOCALE is "en".

Performance reference

These reference measurements were taken from the public noctalia project in August 2026. They describe website requests without a local cache.

Operation Requests Reference result
project() One project page request Progress for 25 locales, about 23 KB
catalog() One complete export 42,857 strings, about 2.23 MB, 4.4–4.8 s
translations() One batch request Two keys and two locales, about 1.3 KB, about 1.4 s
search_translations() Search pages plus one batch request 19 Simplified Chinese matches, about 1.7 s
missing_keys() One missing query All matching keys for the selected locale
reviews() One review query Matching keys and their English source difference
keys() One key-tree page About 2,474 keys and 147 KB
changes() One request per selected key Example key, about 1.3 KB and 1.4 s
iter_changes() Recent Changes pages until the boundary Depends on the requested range

Latency, server load, and project growth affect these values. Exact queries and text searches do not download the complete catalog.

Development

Install the locked development environment:

uv sync --locked

Run formatting, linting, type checking, and tests:

uv run ruff format --check .
uv run ruff check .
uv run basedpyright
uv run python -m unittest discover -v

Run the live contract tests explicitly to verify every public operation against the current public projects on Noctalia Translate:

uv run python -m unittest tests.live -v

Build and inspect both distributions:

uv build --no-sources --clear
uvx twine check --strict dist/*

License

MIT

Metadata

Release files for noctalia-i18n-core 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for noctalia-i18n-core 0.3.0
File Size Uploaded
noctalia_i18n_core-0.3.0.tar.gz 24.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for noctalia-i18n-core 0.3.0
File Interpreter ABI Platform
noctalia_i18n_core-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 39.6 kB

Release files / noctalia_i18n_core-0.3.0.tar.gz

Download URL noctalia_i18n_core-0.3.0.tar.gz
Size 24.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e1c6a162402aad071723d5617b24564b4e2d255cba39369d3bf5dfba4df47423
BLAKE2b-256 checksum
How to use checksums
bec00e848d19f93fbfb060730648f5a3c0d255cbc6919da75844c3f4e493279b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 8, 2026.

Transparency log

Release files / noctalia_i18n_core-0.3.0-py3-none-any.whl

Download URL noctalia_i18n_core-0.3.0-py3-none-any.whl
Size 15.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b93c51bc3884ef4ca4e95e5374d495b6268cc12432f055e22e6472cf8bbd7394
BLAKE2b-256 checksum
How to use checksums
1b07fe6ac34ff6e4a6b785bb04877e5e8737a6b91a02a9a6e181e06b1b91bc03
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 8, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.2

2 release files

0.3.1

2 release files

This release

0.3.0 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page