Skip to content

Add Persian (fa) locale, and with it the project's first RTL language #7198

Description

@yaser-k

Read This First (Do Not Remove This Section)

  • Docs: https://docs.newapi.ai/
  • Usage questions first: https://deepwiki.com/QuantumNous/new-api
  • Issues about forwarding behavior after enabling pass-through mode are not accepted; pass-through mode forwards requests directly, so please verify upstream behavior yourself.
  • Reports about Coding Plan services, reverse-engineered channels, third-party API wrappers, or compatibility issues caused by exposing a Codex endpoint through a reverse proxy as a general-purpose API are not accepted. Protocols or behavior specific to the Codex API should not be treated as standard OpenAI API behavior; confirm such issues with the channel or API provider first.
  • Warning: issues with this template removed, section headings deleted, or content cleared may be closed directly. Repeated abusive submissions may result in a block.

Your current newapi version
v1.0.0-rc.40 (latest release). Checked again on 2026-09-27 against v1.0.0-rc.40 and main at c2b7a9a: still applies. First filed against v1.0.0-rc.26, which the research below refers to.

Submission Checks

  • Non-duplicate issue: I have searched existing Issues and confirmed there are no similar issues.
  • Read this first: I have fully read the section above, reviewed the docs at https://docs.newapi.ai/ and the project README, and asked AI first, confirming this is not a usage, configuration, or integration question, and that the current version cannot meet my needs.
  • Template intact: I have not removed any guidance or section headings from this template and will complete it as requested.
  • Maintainer time: I understand that maintainers have limited time and issues that do not follow this template may be ignored or closed directly.

Feature Description

Add Persian (fa) as a supported UI locale, and with it the project's first right-to-left language.

Persian is not in the language switcher, and there is no supported way for an operator to add a locale: the language list is a hardcoded array and every dictionary is compiled into the bundle. Confirmed on a running v1.0.0-rc.26 instance, the served JS carries all seven dictionaries inline, with no i18next-http-backend, no loadPath, and nothing fetched from /locales/.

This is a larger request than a translation, which is why it is filed for alignment rather than as a PR. Persian would be the first RTL language in the project, and RTL is the part that needs a maintainer decision.

Use Case

Persian-speaking deployments. More broadly, this is the change that makes any RTL language possible: Arabic, Hebrew and Urdu would follow the same path once the groundwork exists. It would also unblock #6083 (Turkish), since the eighth-locale plumbing is shared even though Turkish itself is LTR.

I have since done the full fa translation in my fork, covering every key the UI uses (see the comments below), and the RTL layout work, and can send it in whatever number of reviewable PRs you prefer. Guidance on splitting it would be welcome, since a single PR of that size is hard to review.

Two questions, which are the reason this is an issue and not a PR

  1. Do you want an RTL language in the project at all? It is a standing commitment, because every future UI change acquires an RTL dimension. A clear "not now" is a useful answer and would save the work.
  2. If yes, how should the locale set stop being hardcoded? That design is yours; the translation is the easy half.

Supporting research (code paths, duplicate check, and what is already present in the bundle)

Usage / configuration / integration check

  • https://docs.newapi.ai/ — searched for locale, language, i18n and theme configuration. The environment-variables page documents no locale-related variable. Conclusion: no supported way to add a language at runtime.
  • https://deepwiki.com/QuantumNous/new-api — reviewed the frontend architecture notes. Conclusion: locales are build-time assets, not runtime configuration.
  • README / repo docs: .agents/skills/i18n-translate/SKILL.md documents the translation workflow and names exactly seven supported locales.
  • Relevant code paths and conclusion: see the Code section below. The language list is a hardcoded array and every dictionary is compiled into the bundle; there is no i18next-http-backend, no loadPath, and nothing served from /locales/. Confirmed against a running v1.0.0-rc.26 instance: the served JS contains all seven dictionaries inline.
  • Can the current version already do this? (required for feature requests): No. An operator cannot add a language without rebuilding the frontend.
  • Verdict: new feature.

Environment

  • new-api version / commit / image tag (not latest / unknown): v1.0.0-rc.26, pinned by digest
  • Deploy source (repo release / official image / main source / other): official image
  • Database (sqlite / mysql / postgres): postgres 16

Problem facts

  • Actual behavior: The language switcher offers seven locales (zhCN, en, fr, ru, ja, vi, zhTW). Persian is not among them, and there is no supported way for an operator to add one.
  • Impact: Persian-speaking end users see an English or Chinese panel. For non-technical users this affects the pages they rely on most, including wallet, keys and usage.
  • Frequency: constant.
  • Evidence that the problem is in new-api rather than the client or upstream: the locale set is defined in this repository at web/src/i18n/languages.ts and compiled into the bundle.

Type-specific details

Relay / API

not applicable

Billing

not applicable

Frontend

  • Page path: entire panel; the language switcher in the header
  • Browser and version: Chrome 141
  • Active theme: default
  • Relevant browser Console / Network errors: none. This is missing functionality, not an error.

Deployment / upgrade

not applicable

Reproduction and expected result

  • Steps to reproduce: open the panel, open the language switcher.
  • Expected result: Persian is selectable and the UI renders right-to-left.
  • Related screenshots (optional): not applicable.

Feature (feature requests only)

  • Feature description: Add Persian (fa) as a supported UI locale, and with it the first right-to-left language in the project.
  • Use case: Persian-speaking deployments. More generally, this is the change that makes any RTL language possible; Arabic, Hebrew and Urdu would follow the same path once the groundwork exists.

Duplicate check

Research

Docs

  • https://docs.newapi.ai/ : no locale or language configuration documented anywhere, including the environment-variables reference.
  • https://deepwiki.com/QuantumNous/new-api : frontend architecture confirms build-time i18n.
  • README / other repo docs: .agents/skills/i18n-translate/SKILL.md states the supported set is en, zh, zh-TW, fr, ja, ru, vi, requires all locale writes to go through add-missing-keys.mjs followed by bun run i18n:sync, and forbids hand-editing the JSON.
  • Conclusions: adding a locale is a code change plus a tooling change, not a file drop.

Code

  • web/src/i18n/languages.ts — the hardcoded array the switcher renders: [{code:"zhCN"},{code:"en"},{code:"fr"},{code:"ru"},{code:"ja"},{code:"vi"},{code:"zhTW"}].
  • web/src/i18n/config.ts — i18next initialisation and resource registration.
  • web/src/lib/localized-text.ts and its test — locale-aware text handling that enumerates the same set.
  • web/src/i18n/locales/*.json — seven files, 6,778 keys each in v1.0.0-rc.40 (5,538 at filing), flat under "translation", English source strings as keys.
  • web/scripts/add-missing-keys.mjs and i18n:sync — the mandated write path, which assumes the seven-locale set.
  • i18n/locales/*.yaml — the backend set is separate and smaller: en, zh-CN, zh-TW only.
  • Relation: an eighth locale touches the language array, the i18next config, the localized-text helper and its test, and the locale tooling. The backend YAML set is a separate, optional question.

Experiments

  • Command or redacted request: inspected the compiled bundle served by a running v1.0.0-rc.26 instance.
  • Direct upstream result: not applicable.
  • Result through new-api: the served JS contains all seven dictionaries inline; no locale file is fetched over HTTP at runtime. The served CSS already contains Tailwind's rtl: variant, compiled against a :lang() list that includes fa, and useDirection / setAttribute("dir") are present from Base UI.
  • Conclusion: some RTL capability is already compiled in and unused. The gap is layout correctness, not primitives.

Working theory

  • What is broken or missing: there is no eighth-locale path, and no RTL layout support has been exercised because all seven current locales are LTR.
  • Why: the locale set is hardcoded in several places and the tooling is written around exactly seven files. Separately, the stylesheet mixes logical and physical CSS properties, so dir="rtl" alone will not produce a correct layout.
  • What would falsify this: a maintainer pointing to an existing extension point for locales, or to RTL work already in progress.

Scope

  • In scope for a later PR: adding fa to the language list, i18next config and localized-text helper; producing the fa.json locale through the sanctioned script; and the CSS changes needed for correct RTL layout.
  • Out of scope / not this repo: Persian translation of the backend YAML locales, unless maintainers want it in the same change; and translation of the documentation site.
  • Large or directional feature? If yes, this issue is for maintainer alignment; do not open a PR yet. Yes. Filed for alignment before any PR, per this template.

Proposed direction

Acceptance criteria, offered for discussion rather than as a fixed design:

  1. Persian appears in the language switcher and the panel renders in Persian.
  2. Selecting an RTL locale sets dir="rtl" on the document root, and the panel layout mirrors correctly: navigation, sidebar, tables, form controls, drawers, dropdown alignment and icon direction.
  3. The locale tooling accepts a locale set that is not fixed at seven, so a ninth is cheaper than the eighth.
  4. No regression for the seven existing LTR locales.

Two questions for maintainers, which are the reason this is an issue and not a PR:

  • Do you want an RTL language in the project at all? It is a larger commitment than a translation, because every future UI change acquires an RTL dimension. A clear "not now" is a useful answer and would save the work.
  • If yes, how should the locale set stop being hardcoded? That decision is yours; the translation is the easy half.

The full fa translation, covering every key the UI uses, and the RTL layout work are now done in the fork (see the comments below); they can be sent in whatever number of reviewable PRs you prefer. Guidance on splitting it would be welcome, since a single PR of that size is hard to review.

Not verified

  • How the seven existing locales render once dir="rtl" is introduced; no RTL rendering has been tested.
  • Whether the backend YAML locales are expected to track the frontend set.
  • Whether web/classic on main is intended to receive locales too. This issue is written against the web/ app as it exists in v1.0.0-rc.26.
  • Persian rendering of the Playground and any chart or code-viewer components.

Related


Resubmitted from #7197, which was auto-closed for missing the standard template sections. Same content, correct template.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions