diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml
index 564fb6e66..c303ec09a 100644
--- a/.github/workflows/checks.yml
+++ b/.github/workflows/checks.yml
@@ -139,7 +139,7 @@ jobs:
set -x
sudo apt update
- sudo apt install portaudio19-dev gettext
+ sudo apt install portaudio19-dev
curl -L https://github.com/bazelbuild/bazelisk/releases/download/v1.7.4/bazelisk-linux-amd64 -o ./bazel && \
chmod +x ./bazel
diff --git a/docs/linux.md b/docs/linux.md
index 3e7c4ba11..794b2790b 100644
--- a/docs/linux.md
+++ b/docs/linux.md
@@ -7,7 +7,7 @@ These instructions are written for Debian/Ubuntu; adjust for your distribution.
**Ensure some basic tools are installed**:
```
-$ sudo apt install bash grep findutils curl gcc g++ git gettext
+$ sudo apt install bash grep findutils curl gcc g++ git
```
The 'find' utility is 'findutils' on Debian.
diff --git a/docs/mac.md b/docs/mac.md
index ddb2bb249..2a6aa9d43 100644
--- a/docs/mac.md
+++ b/docs/mac.md
@@ -14,7 +14,7 @@ Install Homebrew from
Then install deps:
```
-$ brew install rsync gettext bazelisk
+$ brew install rsync bazelisk
```
**Install Python 3.8**:
diff --git a/docs/windows.md b/docs/windows.md
index ba1de3388..aeebb229e 100644
--- a/docs/windows.md
+++ b/docs/windows.md
@@ -31,7 +31,7 @@ Install [msys2](https://www.msys2.org/) into the default folder location.
After installation completes, run msys2, and run the following command:
```
-$ pacman -S git gettext
+$ pacman -S git
```
**Bazelisk**:
diff --git a/pylib/anki/lang.py b/pylib/anki/lang.py
index ee3ea14ac..74496d1f5 100644
--- a/pylib/anki/lang.py
+++ b/pylib/anki/lang.py
@@ -1,13 +1,10 @@
-# -*- coding: utf-8 -*-
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-# Please leave the coding line in this file to prevent xgettext complaining.
from __future__ import annotations
-import gettext
import re
-from typing import Optional, Union
+from typing import Optional
import anki
@@ -142,11 +139,6 @@ def lang_to_disk_lang(lang: str) -> str:
# the currently set interface language
currentLang = "en"
-# the current gettext translation catalog
-current_catalog: Optional[
- Union[gettext.NullTranslations, gettext.GNUTranslations]
-] = None
-
# the current Fluent translation instance
current_i18n: Optional[anki.rsbackend.RustBackend] = None
@@ -155,10 +147,13 @@ locale_folder = ""
def _(str: str) -> str:
- if current_catalog:
- return current_catalog.gettext(str)
- else:
- return str
+ print(f"gettext _() is deprecated: {str}")
+ return str
+
+
+def ngettext(single: str, plural: str, n: int) -> str:
+ print(f"ngettext() is deprecated: {plural}")
+ return plural
def tr_legacyglobal(*args, **kwargs) -> str:
@@ -169,26 +164,10 @@ def tr_legacyglobal(*args, **kwargs) -> str:
return "tr_legacyglobal() called without active backend"
-def ngettext(single: str, plural: str, n: int) -> str:
- if current_catalog:
- return current_catalog.ngettext(single, plural, n)
- elif n == 1:
- return single
- return plural
-
-
def set_lang(lang: str, locale_dir: str) -> None:
- global currentLang, current_catalog, current_i18n, locale_folder
- gettext_dir = locale_dir
- ftl_dir = locale_dir
-
+ global currentLang, current_i18n, locale_folder
currentLang = lang
- current_catalog = gettext.translation(
- "anki", gettext_dir, languages=[lang], fallback=True
- )
-
- current_i18n = anki.rsbackend.RustBackend(ftl_folder=ftl_dir, langs=[lang])
-
+ current_i18n = anki.rsbackend.RustBackend(ftl_folder=locale_folder, langs=[lang])
locale_folder = locale_dir
diff --git a/qt/aqt/__init__.py b/qt/aqt/__init__.py
index ec5d5d523..2317b4c67 100644
--- a/qt/aqt/__init__.py
+++ b/qt/aqt/__init__.py
@@ -4,7 +4,6 @@
import argparse
import builtins
import getpass
-import gettext
import locale
import os
import sys
@@ -167,7 +166,7 @@ dialogs = DialogManager()
# Language handling
##########################################################################
# Qt requires its translator to be installed before any GUI widgets are
-# loaded, and we need the Qt language to match the gettext language or
+# loaded, and we need the Qt language to match the i18n language or
# translated shortcuts will not work.
# A reference to the Qt translator needs to be held to prevent it from
@@ -202,7 +201,7 @@ def setupLangAndBackend(
lang = force or pm.meta["defaultLang"]
lang = anki.lang.lang_to_disk_lang(lang)
- # load gettext catalog
+ # set active language
ldir = locale_dir()
anki.lang.set_lang(lang, ldir)
diff --git a/qt/aqt/data/BUILD.bazel b/qt/aqt/data/BUILD.bazel
index 4512cbe44..98324bb90 100644
--- a/qt/aqt/data/BUILD.bazel
+++ b/qt/aqt/data/BUILD.bazel
@@ -1,7 +1,6 @@
filegroup(
name = "data",
srcs = [
- "//qt/aqt/data/locale",
"//qt/aqt/data/web",
],
visibility = ["//qt:__subpackages__"],
diff --git a/qt/aqt/data/locale/BUILD.bazel b/qt/aqt/data/locale/BUILD.bazel
deleted file mode 100644
index 1fb916e8d..000000000
--- a/qt/aqt/data/locale/BUILD.bazel
+++ /dev/null
@@ -1,6 +0,0 @@
-load("//qt/po:gettext.bzl", "compile_all_po_files")
-
-compile_all_po_files(
- name = "locale",
- visibility = ["//qt:__subpackages__"],
-)
diff --git a/qt/aqt/pinnedmodules.py b/qt/aqt/pinnedmodules.py
index eee5660b0..70c7b86a4 100644
--- a/qt/aqt/pinnedmodules.py
+++ b/qt/aqt/pinnedmodules.py
@@ -9,6 +9,7 @@
# included implicitly in the past, and relied upon by some add-ons
import cgi
import decimal
+import gettext
# useful for add-ons
import logging
diff --git a/qt/po/.gitignore b/qt/po/.gitignore
deleted file mode 100644
index 334750928..000000000
--- a/qt/po/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-strings*.json
diff --git a/qt/po/BUILD.bazel b/qt/po/BUILD.bazel
deleted file mode 100644
index cdca3e8a3..000000000
--- a/qt/po/BUILD.bazel
+++ /dev/null
@@ -1,17 +0,0 @@
-load(":gettext.bzl", "build_template", "update_all_po_files")
-
-build_template(
- name = "pot",
- srcs = [
- "//pylib/anki:py_source_files",
- "//qt/aqt:py_source_files",
- "//qt/aqt/forms",
- ],
- pot_file = "anki.pot",
-)
-
-update_all_po_files(
- name = "po_files",
- pot_file = "anki.pot",
- visibility = ["//qt/aqt:__subpackages__"],
-)
diff --git a/qt/po/gettext.bzl b/qt/po/gettext.bzl
deleted file mode 100644
index e5279b05b..000000000
--- a/qt/po/gettext.bzl
+++ /dev/null
@@ -1,148 +0,0 @@
-_langs = [
- "af",
- "ar",
- "bg",
- "ca",
- "cs",
- "da",
- "de",
- "el",
- "en-GB",
- "eo",
- "es",
- "et",
- "eu",
- "fa",
- "fi",
- "fr",
- "ga-IE",
- "gl",
- "he",
- "hi-IN",
- "hr",
- "hu",
- "hy-AM",
- "it",
- "ja",
- "jbo",
- "kab",
- # "km",
- "ko",
- "la",
- "mn",
- "mr",
- "ms",
- "nb-NO",
- "nl",
- "nn-NO",
- "oc",
- "or",
- "pl",
- "pt-BR",
- "pt-PT",
- "ro",
- "ru",
- "sk",
- "sl",
- "sr",
- "sv-SE",
- "th",
- "tr",
- "uk",
- # "ur",
- "vi",
- "zh-CN",
- "zh-TW",
-]
-
-# homebrew gettext is not on path by default
-_pathfix = """export PATH="$$PATH":/usr/local/opt/gettext/bin\n"""
-
-def update_po(name, po_file_in, po_file_out, pot_file, visibility):
- "Merge old .po and latest strings from .pot into new .po"
- native.genrule(
- name = name,
- srcs = [po_file_in, pot_file],
- outs = [po_file_out],
- cmd = _pathfix + """\
-msgmerge -q -F --no-wrap $(location {po_file_in}) $(location {pot_file}) > $(location {po_file_out})
-""".format(
- po_file_in = po_file_in,
- po_file_out = po_file_out,
- pot_file = pot_file,
- ),
- message = "Updating translation",
- visibility = visibility,
- )
-
-def compile_po(name, po_file, mo_file):
- "Build .mo file from an updated .po file."
- native.genrule(
- name = name,
- srcs = [po_file],
- outs = [mo_file],
- cmd = _pathfix + """\
-cat $(location {po_file}) | msgfmt - --output-file=$(location {mo_file})
-""".format(
- po_file = po_file,
- mo_file = mo_file,
- ),
- message = "Compiling translation",
- )
-
-def build_template(name, pot_file, srcs):
- "Build .pot file from Python files."
- native.genrule(
- name = name,
- srcs = srcs,
- outs = [pot_file],
- cmd = _pathfix + """\
-all=all.files
-for i in $(SRCS); do
- echo $$i >> $$all
-done
-xgettext -cT: -s --no-wrap --files-from=$$all --output=$(OUTS)
-rm $$all
-""",
- message = "Building .pot template",
- )
-
-def update_all_po_files(name, pot_file, visibility):
- # merge external .po files with updated .pot
- po_files = []
- for lang in _langs:
- po_file_in = "@aqt_po//:desktop/{}/anki.po".format(lang)
- po_file_out = "{}/anki.po".format(lang)
- update_po(
- name = lang + "_po",
- po_file_in = po_file_in,
- po_file_out = po_file_out,
- pot_file = pot_file,
- visibility = visibility,
- )
- po_files.append(po_file_out)
-
- native.filegroup(
- name = name,
- srcs = po_files,
- visibility = visibility,
- )
-
-def compile_all_po_files(name, visibility):
- "Build all .mo files from .po files."
- mo_files = []
- for lang in _langs:
- po_file = "//qt/po:{}/anki.po".format(lang)
- mo_file = "{}/LC_MESSAGES/anki.mo".format(lang)
- compile_po(
- name = lang + "_mo",
- po_file = po_file,
- mo_file = mo_file,
- )
- mo_files.append(mo_file)
-
- native.filegroup(
- name = name,
- srcs = mo_files,
- visibility = visibility,
- )
diff --git a/qt/po/plurals.json b/qt/po/plurals.json
deleted file mode 100644
index bac5eda6a..000000000
--- a/qt/po/plurals.json
+++ /dev/null
@@ -1,889 +0,0 @@
-{
- "af": [
- "one",
- "other"
- ],
- "ak": [
- "one",
- "other"
- ],
- "am": [
- "one",
- "other"
- ],
- "an": [
- "one",
- "other"
- ],
- "ar": [
- "zero",
- "one",
- "two",
- "few",
- "many",
- "other"
- ],
- "ars": [
- "zero",
- "one",
- "two",
- "few",
- "many",
- "other"
- ],
- "as": [
- "one",
- "other"
- ],
- "asa": [
- "one",
- "other"
- ],
- "ast": [
- "one",
- "other"
- ],
- "az": [
- "one",
- "other"
- ],
- "be": [
- "one",
- "few",
- "many",
- "other"
- ],
- "bem": [
- "one",
- "other"
- ],
- "bez": [
- "one",
- "other"
- ],
- "bg": [
- "one",
- "other"
- ],
- "bho": [
- "one",
- "other"
- ],
- "bm": [
- "other"
- ],
- "bn": [
- "one",
- "other"
- ],
- "bo": [
- "other"
- ],
- "br": [
- "one",
- "two",
- "few",
- "many",
- "other"
- ],
- "brx": [
- "one",
- "other"
- ],
- "bs": [
- "one",
- "few",
- "other"
- ],
- "ca": [
- "one",
- "other"
- ],
- "ce": [
- "one",
- "other"
- ],
- "ceb": [
- "one",
- "other"
- ],
- "cgg": [
- "one",
- "other"
- ],
- "chr": [
- "one",
- "other"
- ],
- "ckb": [
- "one",
- "other"
- ],
- "cs": [
- "one",
- "few",
- "many",
- "other"
- ],
- "cy": [
- "zero",
- "one",
- "two",
- "few",
- "many",
- "other"
- ],
- "da": [
- "one",
- "other"
- ],
- "de": [
- "one",
- "other"
- ],
- "dsb": [
- "one",
- "two",
- "few",
- "other"
- ],
- "dv": [
- "one",
- "other"
- ],
- "dz": [
- "other"
- ],
- "ee": [
- "one",
- "other"
- ],
- "el": [
- "one",
- "other"
- ],
- "en": [
- "one",
- "other"
- ],
- "eo": [
- "one",
- "other"
- ],
- "es": [
- "one",
- "other"
- ],
- "et": [
- "one",
- "other"
- ],
- "eu": [
- "one",
- "other"
- ],
- "fa": [
- "one",
- "other"
- ],
- "ff": [
- "one",
- "other"
- ],
- "fi": [
- "one",
- "other"
- ],
- "fil": [
- "one",
- "other"
- ],
- "fo": [
- "one",
- "other"
- ],
- "fr": [
- "one",
- "other"
- ],
- "fur": [
- "one",
- "other"
- ],
- "fy": [
- "one",
- "other"
- ],
- "ga": [
- "one",
- "two",
- "few",
- "many",
- "other"
- ],
- "gd": [
- "one",
- "two",
- "few",
- "other"
- ],
- "gl": [
- "one",
- "other"
- ],
- "gsw": [
- "one",
- "other"
- ],
- "gu": [
- "one",
- "other"
- ],
- "guw": [
- "one",
- "other"
- ],
- "gv": [
- "one",
- "two",
- "few",
- "many",
- "other"
- ],
- "ha": [
- "one",
- "other"
- ],
- "haw": [
- "one",
- "other"
- ],
- "he": [
- "one",
- "two",
- "many",
- "other"
- ],
- "hi": [
- "one",
- "other"
- ],
- "hr": [
- "one",
- "few",
- "other"
- ],
- "hsb": [
- "one",
- "two",
- "few",
- "other"
- ],
- "hu": [
- "one",
- "other"
- ],
- "hy": [
- "one",
- "other"
- ],
- "ia": [
- "one",
- "other"
- ],
- "id": [
- "other"
- ],
- "ig": [
- "other"
- ],
- "ii": [
- "other"
- ],
- "in": [
- "other"
- ],
- "io": [
- "one",
- "other"
- ],
- "is": [
- "one",
- "other"
- ],
- "it": [
- "one",
- "other"
- ],
- "iu": [
- "one",
- "two",
- "other"
- ],
- "iw": [
- "one",
- "two",
- "many",
- "other"
- ],
- "ja": [
- "other"
- ],
- "jbo": [
- "other"
- ],
- "jgo": [
- "one",
- "other"
- ],
- "ji": [
- "one",
- "other"
- ],
- "jmc": [
- "one",
- "other"
- ],
- "jv": [
- "other"
- ],
- "jw": [
- "other"
- ],
- "ka": [
- "one",
- "other"
- ],
- "kab": [
- "one",
- "other"
- ],
- "kaj": [
- "one",
- "other"
- ],
- "kcg": [
- "one",
- "other"
- ],
- "kde": [
- "other"
- ],
- "kea": [
- "other"
- ],
- "kk": [
- "one",
- "other"
- ],
- "kkj": [
- "one",
- "other"
- ],
- "kl": [
- "one",
- "other"
- ],
- "km": [
- "other"
- ],
- "kn": [
- "one",
- "other"
- ],
- "ko": [
- "other"
- ],
- "ks": [
- "one",
- "other"
- ],
- "ksb": [
- "one",
- "other"
- ],
- "ksh": [
- "zero",
- "one",
- "other"
- ],
- "ku": [
- "one",
- "other"
- ],
- "kw": [
- "zero",
- "one",
- "two",
- "few",
- "many",
- "other"
- ],
- "ky": [
- "one",
- "other"
- ],
- "lag": [
- "zero",
- "one",
- "other"
- ],
- "lb": [
- "one",
- "other"
- ],
- "lg": [
- "one",
- "other"
- ],
- "lkt": [
- "other"
- ],
- "ln": [
- "one",
- "other"
- ],
- "lo": [
- "other"
- ],
- "lt": [
- "one",
- "few",
- "many",
- "other"
- ],
- "lv": [
- "zero",
- "one",
- "other"
- ],
- "mas": [
- "one",
- "other"
- ],
- "mg": [
- "one",
- "other"
- ],
- "mgo": [
- "one",
- "other"
- ],
- "mk": [
- "one",
- "other"
- ],
- "ml": [
- "one",
- "other"
- ],
- "mn": [
- "one",
- "other"
- ],
- "mo": [
- "one",
- "few",
- "other"
- ],
- "mr": [
- "one",
- "other"
- ],
- "ms": [
- "other"
- ],
- "mt": [
- "one",
- "few",
- "many",
- "other"
- ],
- "my": [
- "other"
- ],
- "nah": [
- "one",
- "other"
- ],
- "naq": [
- "one",
- "two",
- "other"
- ],
- "nb": [
- "one",
- "other"
- ],
- "nd": [
- "one",
- "other"
- ],
- "ne": [
- "one",
- "other"
- ],
- "nl": [
- "one",
- "other"
- ],
- "nn": [
- "one",
- "other"
- ],
- "nnh": [
- "one",
- "other"
- ],
- "no": [
- "one",
- "other"
- ],
- "nqo": [
- "other"
- ],
- "nr": [
- "one",
- "other"
- ],
- "nso": [
- "one",
- "other"
- ],
- "ny": [
- "one",
- "other"
- ],
- "nyn": [
- "one",
- "other"
- ],
- "om": [
- "one",
- "other"
- ],
- "or": [
- "one",
- "other"
- ],
- "os": [
- "one",
- "other"
- ],
- "osa": [
- "other"
- ],
- "pa": [
- "one",
- "other"
- ],
- "pap": [
- "one",
- "other"
- ],
- "pl": [
- "one",
- "few",
- "many",
- "other"
- ],
- "prg": [
- "zero",
- "one",
- "other"
- ],
- "ps": [
- "one",
- "other"
- ],
- "pt": [
- "one",
- "other"
- ],
- "pt-PT": [
- "one",
- "other"
- ],
- "rm": [
- "one",
- "other"
- ],
- "ro": [
- "one",
- "few",
- "other"
- ],
- "rof": [
- "one",
- "other"
- ],
- "root": [
- "other"
- ],
- "ru": [
- "one",
- "few",
- "many",
- "other"
- ],
- "rwk": [
- "one",
- "other"
- ],
- "sah": [
- "other"
- ],
- "saq": [
- "one",
- "other"
- ],
- "sc": [
- "one",
- "other"
- ],
- "scn": [
- "one",
- "other"
- ],
- "sd": [
- "one",
- "other"
- ],
- "sdh": [
- "one",
- "other"
- ],
- "se": [
- "one",
- "two",
- "other"
- ],
- "seh": [
- "one",
- "other"
- ],
- "ses": [
- "other"
- ],
- "sg": [
- "other"
- ],
- "sh": [
- "one",
- "few",
- "other"
- ],
- "shi": [
- "one",
- "few",
- "other"
- ],
- "si": [
- "one",
- "other"
- ],
- "sk": [
- "one",
- "few",
- "many",
- "other"
- ],
- "sl": [
- "one",
- "two",
- "few",
- "other"
- ],
- "sma": [
- "one",
- "two",
- "other"
- ],
- "smi": [
- "one",
- "two",
- "other"
- ],
- "smj": [
- "one",
- "two",
- "other"
- ],
- "smn": [
- "one",
- "two",
- "other"
- ],
- "sms": [
- "one",
- "two",
- "other"
- ],
- "sn": [
- "one",
- "other"
- ],
- "so": [
- "one",
- "other"
- ],
- "sq": [
- "one",
- "other"
- ],
- "sr": [
- "one",
- "few",
- "other"
- ],
- "ss": [
- "one",
- "other"
- ],
- "ssy": [
- "one",
- "other"
- ],
- "st": [
- "one",
- "other"
- ],
- "su": [
- "other"
- ],
- "sv": [
- "one",
- "other"
- ],
- "sw": [
- "one",
- "other"
- ],
- "syr": [
- "one",
- "other"
- ],
- "ta": [
- "one",
- "other"
- ],
- "te": [
- "one",
- "other"
- ],
- "teo": [
- "one",
- "other"
- ],
- "th": [
- "other"
- ],
- "ti": [
- "one",
- "other"
- ],
- "tig": [
- "one",
- "other"
- ],
- "tk": [
- "one",
- "other"
- ],
- "tl": [
- "one",
- "other"
- ],
- "tn": [
- "one",
- "other"
- ],
- "to": [
- "other"
- ],
- "tr": [
- "one",
- "other"
- ],
- "ts": [
- "one",
- "other"
- ],
- "tzm": [
- "one",
- "other"
- ],
- "ug": [
- "one",
- "other"
- ],
- "uk": [
- "one",
- "few",
- "many",
- "other"
- ],
- "ur": [
- "one",
- "other"
- ],
- "uz": [
- "one",
- "other"
- ],
- "ve": [
- "one",
- "other"
- ],
- "vi": [
- "other"
- ],
- "vo": [
- "one",
- "other"
- ],
- "vun": [
- "one",
- "other"
- ],
- "wa": [
- "one",
- "other"
- ],
- "wae": [
- "one",
- "other"
- ],
- "wo": [
- "other"
- ],
- "xh": [
- "one",
- "other"
- ],
- "xog": [
- "one",
- "other"
- ],
- "yi": [
- "one",
- "other"
- ],
- "yo": [
- "other"
- ],
- "yue": [
- "other"
- ],
- "zh": [
- "other"
- ],
- "zu": [
- "one",
- "other"
- ],
- "oc":
- ["one", "other"],
- "la":
- ["one", "other"]
-}
diff --git a/qt/po/requirements.txt b/qt/po/requirements.txt
deleted file mode 100644
index 23e5826d6..000000000
--- a/qt/po/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-polib
diff --git a/qt/po/scripts/extract-po-strings.py b/qt/po/scripts/extract-po-strings.py
deleted file mode 100644
index 934ea4581..000000000
--- a/qt/po/scripts/extract-po-strings.py
+++ /dev/null
@@ -1,313 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: UTF-8 -*-
-
-import os
-import json
-import polib
-import pprint
-import re
-
-# Read strings from all .po and .pot files and store them in a JSON file
-# for quick access.
-
-# returns a string, an array of plurals, or None if there's no translation
-def get_msgstr(entry):
- # non-empty single string?
- if entry.msgstr:
- return entry.msgstr
- # plural string and non-empty?
- elif entry.msgstr_plural and entry.msgstr_plural[0]:
- # convert the dict into a list in the correct order
- plurals = list(entry.msgstr_plural.items())
- plurals.sort()
- # update variables and discard keys
- adjusted = []
- for _k, msg in plurals:
- assert msg
- adjusted.append(msg)
- if len(adjusted) > 1 and adjusted[0]:
- return adjusted
- else:
- if adjusted[0]:
- return adjusted[0]
- return None
-
-
-module_map = {
- "__init__": "qt-misc",
- "about": "about",
- "addcards": "adding",
- "addfield": "fields",
- "addmodel": "notetypes",
- "addonconf": "addons",
- "addons": "addons",
- "anki2": "importing",
- "browser": "browsing",
- "browserdisp": "browsing",
- "browseropts": "browsing",
- "changemap": "browsing",
- "changemodel": "browsing",
- "clayout_top": "card-templates",
- "clayout": "card-templates",
- "collection": "collection",
- "consts": "consts",
- "csvfile": "importing",
- "customstudy": "custom-study",
- "dconf": "scheduling",
- "debug": "qt-misc",
- "deckbrowser": "decks",
- "deckchooser": "qt-misc",
- "deckconf": "scheduling",
- "decks": "decks",
- "dyndconf": "decks",
- "dyndeckconf": "decks",
- "editaddon": "addons",
- "editcurrent": "editing",
- "edithtml": "editing",
- "editor": "editing",
- "errors": "qt-misc",
- "exporting": "exporting",
- "fields": "fields",
- "finddupes": "browsing",
- "findreplace": "browsing",
- "getaddons": "addons",
- "importing": "importing",
- "latex": "media",
- "main": "qt-misc",
- "mnemo": "importing",
- "modelchooser": "qt-misc",
- "modelopts": "notetypes",
- "models": "notetypes",
- "noteimp": "importing",
- "overview": "studying",
- "preferences": "preferences",
- "previewer": "qt-misc",
- "profiles": "profiles",
- "progress": "qt-misc",
- "reposition": "browsing",
- "reschedule": "browsing",
- "reviewer": "studying",
- "schedv2": "scheduling",
- "setgroup": "browsing",
- "setlang": "preferences",
- "sidebar": "browsing",
- "sound": "media",
- "studydeck": "decks",
- "taglimit": "custom-study",
- "template": "card-templates",
- "toolbar": "qt-misc",
- "update": "qt-misc",
- "utils": "qt-misc",
- "webview": "qt-misc",
- "stats": "statistics",
-}
-
-text_remap = {
- "actions": [
- "Add",
- "Cancel",
- "Choose",
- "Close",
- "Copy",
- "Decks",
- "Delete",
- "Export",
- "Filter",
- "Help",
- "Import",
- "Manage...",
- "Name:",
- "New name:",
- "New",
- "Options for %s",
- "Options",
- "Preview",
- "Rebuild",
- "Rename Deck",
- "Rename",
- "Replay Audio",
- "Reposition",
- "Save",
- "Search",
- "Shortcut key: %s",
- "Suspend Card",
- "Blue Flag",
- "Green Flag",
- "Orange Flag",
- "Red Flag",
- "Custom Study",
- ],
- "decks": [
- "Deck",
- "New deck name:",
- "Decreasing intervals",
- "Increasing intervals",
- "Latest added first",
- "Most lapses",
- "Oldest seen first",
- "Order added",
- "Order due",
- "Random",
- "Relative overdueness",
- ],
- "scheduling": [
- "days",
- "Lapses",
- "Reviews",
- "At least one step is required.",
- "Steps must be numbers.",
- "Show new cards in order added",
- "Show new cards in random order",
- "Show new cards after reviews",
- "Show new cards before reviews",
- "Mix new cards and reviews",
- "Learning",
- "Review",
- ],
- "fields": ["Add Field"],
- "editing": ["Tags", "Cards", "Fields", "LaTeX"],
- "notetypes": ["Type", "Note Types"],
- "studying": ["Space"],
- "qt-misc": ["&Edit", "&Guide...", "&Help", "&Undo", "Unexpected response code: %s"],
- "adding": ["Added"],
-}
-
-blacklist = {"Anki", "%", "Dialog", "Center", "Left", "Right", "~", "&Cram..."}
-
-
-def determine_module(text, files):
- if text in blacklist:
- return None
-
- if "&" in text:
- return "qt-accel"
-
- for (module, texts) in text_remap.items():
- if text in texts:
- return module
-
- if len(files) == 1:
- return list(files)[0]
-
- assert False
-
-
-modules = dict()
-
-remap_keys = {
- "browsing-": "browsing-type-here-to-search",
- "importing-": "importing-ignored",
- "qt-misc-": "qt-misc-non-unicode-text",
-}
-
-
-def generate_key(module: str, text: str) -> str:
- key = re.sub("<.*?>", "", text)
- key = re.sub("%[dsf.0-9]+", "", key)
- key = key.replace("+", "and")
- key = re.sub("[^a-z0-9 ]", "", key.lower())
- words = key.split(" ")
- if len(words) > 6:
- words = words[:6]
- key = "-".join(words)
- key = re.sub("--+", "-", key)
- key = re.sub("-$|^-", "", key)
-
- key = f"{module}-{key}"
-
- if key in remap_keys:
- key = remap_keys[key]
-
- return key
-
-
-seen_keys = set()
-
-
-def migrate_entry(entry):
- if entry.msgid_plural:
- # print("skip plural", entry.msgid)
- return
-
- entry.occurrences = [e for e in entry.occurrences if "aqt/stats.py" in e[0]]
- if not entry.occurrences:
- return None
-
- print(entry.occurrences)
- text = entry.msgid
- files = set(
- [os.path.splitext(os.path.basename(e[0]))[0] for e in entry.occurrences]
- )
-
- files2 = set()
- for file in files:
- file = module_map[file]
- files2.add(file)
- module = determine_module(text, files2)
- if not module:
- return
-
- key = generate_key(module, text)
-
- if key in seen_keys:
- key += "2"
- assert key not in seen_keys
- seen_keys.add(key)
-
- modules.setdefault(module, [])
- modules[module].append((key, text))
-
- return None
-
-
-langs = {}
-
-# .pot first
-base = "../../../anki-i18n/qtpo/desktop"
-pot = os.path.join(base, "anki.pot")
-pot_cat = polib.pofile(pot)
-
-migration_map = []
-
-for entry in pot_cat:
- if entry.msgid_plural:
- msgstr = [entry.msgid, entry.msgid_plural]
- else:
- msgstr = entry.msgid
-
- langs.setdefault("en", {})[entry.msgid] = msgstr
-
- if d := migrate_entry(entry):
- migration_map.append(d)
-
-
-# then .po files
-folders = (d for d in os.listdir(base) if d != "anki.pot")
-for lang in folders:
- po_path = os.path.join(base, lang, "anki.po")
- cat = polib.pofile(po_path)
- for entry in cat:
- msgstr = get_msgstr(entry)
- if not msgstr:
- continue
- langs.setdefault(lang, {})[entry.msgid] = msgstr
-
-with open("strings.json", "w") as file:
- file.write(json.dumps(langs))
-print("wrote to strings.json")
-
-# old text -> (module, new key)
-strings_by_module = {}
-keys_by_text = {}
-for (module, items) in modules.items():
- items.sort()
- strings_by_module[module] = items
- for item in items:
- (key, text) = item
- assert text not in keys_by_text
- keys_by_text[text] = (module, key)
-
-with open("strings_by_module.json", "w") as file:
- file.write(json.dumps(strings_by_module))
-with open("keys_by_text.json", "w") as file:
- file.write(json.dumps(keys_by_text))
diff --git a/qt/po/scripts/extract_po_string.py b/qt/po/scripts/extract_po_string.py
deleted file mode 100644
index adbea66b5..000000000
--- a/qt/po/scripts/extract_po_string.py
+++ /dev/null
@@ -1,245 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: UTF-8 -*-
-
-import os
-import json
-import re
-import sys
-import polib
-import shutil
-import sys
-import subprocess
-from PyQt5.QtWidgets import *
-from PyQt5.QtCore import *
-from PyQt5.QtGui import *
-from extract_po_string_diag import Ui_Dialog
-from fluent.syntax import parse, serialize
-from fluent.syntax.ast import Message, TextElement, Identifier, Pattern, Junk
-
-# the templates folder inside the ftl repo
-repo_templates_dir = sys.argv[1]
-assert os.path.abspath(repo_templates_dir).endswith("templates")
-strings = json.load(open("strings.json" if len(sys.argv) < 3 else sys.argv[2]))
-plurals = json.load(open("plurals.json"))
-
-
-def transform_entry(entry, replacements):
- if isinstance(entry, str):
- return transform_string(entry, replacements)
- else:
- return [transform_string(e, replacements) for e in entry]
-
-
-def transform_string(msg, replacements):
- try:
- for (old, new) in replacements:
- msg = msg.replace(old, f"{new}")
- except ValueError:
- pass
- # strip leading/trailing whitespace
- return msg.strip()
-
-
-def plural_text(key, lang, translation):
- lang = re.sub("(_|-).*", "", lang)
-
- # extract the variable - if there's more than one, use the first one
- var = re.findall(r"{(\$.*?)}", translation[0])
- if not len(var) == 1:
- print("multiple variables found, using first replacement")
- var = replacements[0][1].replace("{", "").replace("}", "")
- else:
- var = var[0]
-
- buf = f"{key} = {{ {var} ->\n"
-
- # for each of the plural forms except the last
- for idx, msg in enumerate(translation[:-1]):
- plural_form = plurals[lang][idx]
- buf += f" [{plural_form}] {msg}\n"
-
- # add the catchall
- msg = translation[-1]
- buf += f" *[other] {msg}\n"
- buf += " }\n"
- return buf
-
-
-def key_from_search(search):
- return search.replace(" ", "-").replace("'", "")
-
-
-# add a non-pluralized message. works via fluent.syntax, so can automatically
-# indent, etc
-def add_simple_message(fname, key, message):
- orig = ""
- if os.path.exists(fname):
- with open(fname) as file:
- orig = file.read()
-
- obj = parse(orig)
- for ent in obj.body:
- if isinstance(ent, Junk):
- raise Exception(f"file had junk! {fname} {ent}")
- obj.body.append(Message(Identifier(key), Pattern([TextElement(message)])))
-
- modified = serialize(obj, with_junk=True)
- # escape leading dots
- modified = re.sub(r"(?ms)^( +)\.", '\\1{"."}', modified)
-
- # ensure the resulting serialized file is valid by parsing again
- obj = parse(modified)
- for ent in obj.body:
- if isinstance(ent, Junk):
- raise Exception(f"introduced junk! {fname} {ent}")
-
- # it's ok, write it out
- with open(fname, "w") as file:
- file.write(modified)
-
-
-def add_message(fname, key, translation):
- # simple, non-plural form?
- if isinstance(translation, str):
- add_simple_message(fname, key, translation)
- else:
- text = plural_text(key, lang, translation)
- open(fname, "a").write(text)
-
-
-def key_already_used(key: str) -> bool:
- return not subprocess.call(["grep", "-r", f"{key} =", repo_templates_dir])
-
-
-class Window(QDialog, Ui_Dialog):
- def __init__(self):
- QDialog.__init__(self)
- self.setupUi(self)
-
- self.matched_strings = []
-
- self.files = sorted(os.listdir(repo_templates_dir))
- self.filenames.addItems(self.files)
-
- self.search.textChanged.connect(self.on_search)
- self.replacements.textChanged.connect(self.update_preview)
- self.key.textEdited.connect(self.update_preview)
- self.filenames.currentIndexChanged.connect(self.update_preview)
- self.searchMatches.currentItemChanged.connect(self.update_preview)
- self.replacementsTemplateButton.clicked.connect(self.on_template)
- self.addButton.clicked.connect(self.on_add)
-
- def on_template(self):
- self.replacements.setText("%d={ $value }")
- # qt macos bug
- self.replacements.repaint()
-
- def on_search(self):
- msgid_substring = self.search.text()
- self.key.setText(key_from_search(msgid_substring))
-
- msgids = []
- exact_idx = None
- for n, id in enumerate(strings["en"].keys()):
- if msgid_substring.lower() in id.lower():
- msgids.append(id)
-
- # is the ID an exact match?
- if msgid_substring in strings["en"]:
- exact_idx = n
-
- self.matched_strings = msgids
- self.searchMatches.clear()
- self.searchMatches.addItems(self.matched_strings)
- if exact_idx is not None:
- self.searchMatches.setCurrentRow(exact_idx)
- elif self.matched_strings:
- self.searchMatches.setCurrentRow(0)
-
- self.update_preview()
-
- def update_preview(self):
- self.preview.clear()
- if not self.matched_strings:
- return
-
- strings = self.get_adjusted_strings()
- key = self.get_key()
- self.preview.setPlainText(
- f"Key: {key}\n\n"
- + "\n".join([f"{lang}: {value}" for (lang, value) in strings])
- )
-
- # returns list of (lang, entry)
- def get_adjusted_strings(self):
- msgid = self.matched_strings[self.searchMatches.currentRow()]
-
- # split up replacements
- replacements = []
- for repl in self.replacements.text().split(","):
- if not repl:
- continue
- replacements.append(repl.split("="))
-
- to_insert = []
- for lang in strings.keys():
- entry = strings[lang].get(msgid)
- if not entry:
- continue
- entry = transform_entry(entry, replacements)
- if entry:
- to_insert.append((lang, entry))
-
- return to_insert
-
- def get_key(self):
- # add file as prefix to key
- prefix = os.path.splitext(self.filenames.currentText())[0]
- return f"{prefix}-{self.key.text()}"
-
- def on_add(self):
- to_insert = self.get_adjusted_strings()
- key = self.get_key()
- if key_already_used(key):
- QMessageBox.warning(None, "Error", "Duplicate Key")
- return
-
- # for each language's translation
- for lang, translation in to_insert:
- ftl_path = self.filename_for_lang(lang)
- add_message(ftl_path, key, translation)
-
- if lang == "en":
- # copy file from repo into src
- srcdir = os.path.join(repo_templates_dir, "..", "..", "..")
- src_filename = os.path.join(srcdir, os.path.basename(ftl_path))
- shutil.copy(ftl_path, src_filename)
-
- subprocess.check_call(
- f"cd {repo_templates_dir} && git add .. && git commit -m 'add {key}'",
- shell=True,
- )
-
- self.preview.setPlainText(f"Added {key}.")
- self.preview.repaint()
-
- def filename_for_lang(self, lang):
- fname = self.filenames.currentText()
- if lang == "en":
- return os.path.join(repo_templates_dir, fname)
- else:
- ftl_dir = os.path.join(repo_templates_dir, "..", lang)
- if not os.path.exists(ftl_dir):
- os.mkdir(ftl_dir)
- return os.path.join(ftl_dir, fname)
-
-
-print("Remember to pull-i18n before making changes.")
-if subprocess.check_output(f"git status --porcelain {repo_templates_dir}", shell=True):
- print("Repo has uncommitted changes.")
- sys.exit(1)
-
-app = QApplication(sys.argv)
-window = Window()
-window.show()
-sys.exit(app.exec_())
diff --git a/qt/po/scripts/extract_po_string_diag.py b/qt/po/scripts/extract_po_string_diag.py
deleted file mode 100644
index e7ca71fea..000000000
--- a/qt/po/scripts/extract_po_string_diag.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Form implementation generated from reading ui file 'extract_po_string_diag.ui'
-#
-# Created by: PyQt5 UI code generator 5.15.0
-#
-# WARNING: Any manual changes made to this file will be lost when pyuic5 is
-# run again. Do not edit this file unless you know what you are doing.
-
-
-from PyQt5 import QtCore, QtGui, QtWidgets
-
-
-class Ui_Dialog(object):
- def setupUi(self, Dialog):
- Dialog.setObjectName("Dialog")
- Dialog.resize(879, 721)
- self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
- self.verticalLayout.setObjectName("verticalLayout")
- self.gridLayout = QtWidgets.QGridLayout()
- self.gridLayout.setObjectName("gridLayout")
- self.label_2 = QtWidgets.QLabel(Dialog)
- self.label_2.setObjectName("label_2")
- self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
- self.filenames = QtWidgets.QComboBox(Dialog)
- self.filenames.setObjectName("filenames")
- self.gridLayout.addWidget(self.filenames, 1, 1, 1, 1)
- self.label_4 = QtWidgets.QLabel(Dialog)
- self.label_4.setObjectName("label_4")
- self.gridLayout.addWidget(self.label_4, 0, 0, 1, 1)
- self.replacementsTemplateButton = QtWidgets.QPushButton(Dialog)
- self.replacementsTemplateButton.setObjectName("replacementsTemplateButton")
- self.gridLayout.addWidget(self.replacementsTemplateButton, 4, 1, 1, 1)
- self.label = QtWidgets.QLabel(Dialog)
- self.label.setObjectName("label")
- self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
- self.label_3 = QtWidgets.QLabel(Dialog)
- self.label_3.setObjectName("label_3")
- self.gridLayout.addWidget(self.label_3, 3, 0, 1, 1)
- self.replacements = QtWidgets.QLineEdit(Dialog)
- self.replacements.setObjectName("replacements")
- self.gridLayout.addWidget(self.replacements, 3, 1, 1, 1)
- self.key = QtWidgets.QLineEdit(Dialog)
- self.key.setObjectName("key")
- self.gridLayout.addWidget(self.key, 2, 1, 1, 1)
- self.search = QtWidgets.QLineEdit(Dialog)
- self.search.setObjectName("search")
- self.gridLayout.addWidget(self.search, 0, 1, 1, 1)
- self.verticalLayout.addLayout(self.gridLayout)
- self.label_5 = QtWidgets.QLabel(Dialog)
- self.label_5.setObjectName("label_5")
- self.verticalLayout.addWidget(self.label_5)
- self.searchMatches = QtWidgets.QListWidget(Dialog)
- self.searchMatches.setObjectName("searchMatches")
- self.verticalLayout.addWidget(self.searchMatches)
- self.label_6 = QtWidgets.QLabel(Dialog)
- self.label_6.setObjectName("label_6")
- self.verticalLayout.addWidget(self.label_6)
- self.preview = QtWidgets.QTextEdit(Dialog)
- self.preview.setObjectName("preview")
- self.verticalLayout.addWidget(self.preview)
- self.addButton = QtWidgets.QPushButton(Dialog)
- self.addButton.setObjectName("addButton")
- self.verticalLayout.addWidget(self.addButton)
-
- self.retranslateUi(Dialog)
- QtCore.QMetaObject.connectSlotsByName(Dialog)
- Dialog.setTabOrder(self.search, self.filenames)
- Dialog.setTabOrder(self.filenames, self.key)
- Dialog.setTabOrder(self.key, self.replacements)
- Dialog.setTabOrder(self.replacements, self.replacementsTemplateButton)
- Dialog.setTabOrder(self.replacementsTemplateButton, self.searchMatches)
- Dialog.setTabOrder(self.searchMatches, self.preview)
- Dialog.setTabOrder(self.preview, self.addButton)
-
- def retranslateUi(self, Dialog):
- _translate = QtCore.QCoreApplication.translate
- Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
- self.label_2.setText(_translate("Dialog", "Fluent key suffix"))
- self.label_4.setText(_translate("Dialog", "Search:"))
- self.replacementsTemplateButton.setText(_translate("Dialog", "Template"))
- self.label.setText(_translate("Dialog", "Target file"))
- self.label_3.setText(_translate("Dialog", "Replacements"))
- self.label_5.setText(_translate("Dialog", "Matches"))
- self.label_6.setText(_translate("Dialog", "Preview"))
- self.addButton.setText(_translate("Dialog", "Add"))
diff --git a/qt/po/scripts/extract_po_string_diag.ui b/qt/po/scripts/extract_po_string_diag.ui
deleted file mode 100644
index c3c9f10d3..000000000
--- a/qt/po/scripts/extract_po_string_diag.ui
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
- Dialog
-
-
-
- 0
- 0
- 879
- 721
-
-
-
- Dialog
-
-
- -
-
-
-
-
-
- Fluent key suffix
-
-
-
- -
-
-
- -
-
-
- Search:
-
-
-
- -
-
-
- Template
-
-
-
- -
-
-
- Target file
-
-
-
- -
-
-
- Replacements
-
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
- -
-
-
- Matches
-
-
-
- -
-
-
- -
-
-
- Preview
-
-
-
- -
-
-
- -
-
-
- Add
-
-
-
-
-
-
- search
- filenames
- key
- replacements
- replacementsTemplateButton
- searchMatches
- preview
- addButton
-
-
-
-
diff --git a/qt/po/scripts/rewrite-refs.py b/qt/po/scripts/rewrite-refs.py
deleted file mode 100644
index 5746be453..000000000
--- a/qt/po/scripts/rewrite-refs.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-
-import glob, re, json, stringcase
-
-files = (
- # glob.glob("../../pylib/**/*.py", recursive=True) +
- glob.glob("../../qt/**/*.py", recursive=True)
-)
-string_re = re.compile(r'_\(\s*(".*?")\s*\)', re.DOTALL)
-
-map = json.load(open("keys_by_text.json"))
-
-# unused or missing strings
-blacklist = {
- "Label1",
- "After pressing OK, you can choose which tags to include.",
- "Filter/Cram",
- # previewer.py needs updating to fix these
- "Shortcut key: R",
- "Shortcut key: B",
-}
-
-
-def repl(m):
- # the argument may consistent of multiple strings that need merging together
- text = eval("(" + m.group(1) + ")")
- print(f"text is `{text}`")
-
- if text in blacklist:
- return m.group(0)
-
- (module, key) = map[text]
- screaming = stringcase.constcase(key)
- print(screaming)
-
- if "%d" in text or "%s" in text:
- # replace { $val } with %s for compat with old code
- return f'tr(TR.{screaming}, val="%s")'
-
- return f"tr(TR.{screaming})"
-
-
-for file in files:
- buf = open(file).read()
- buf2 = string_re.sub(repl, buf)
- if buf != buf2:
- lines = buf2.split("\n")
- lines.insert(3, "from aqt.utils import tr, TR")
- buf2 = "\n".join(lines)
- open(file, "w").write(buf2)
diff --git a/qt/po/scripts/write-ftls.py b/qt/po/scripts/write-ftls.py
deleted file mode 100644
index 2df0acc1e..000000000
--- a/qt/po/scripts/write-ftls.py
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/env python
-
-import json
-import os
-
-from fluent.syntax import parse, serialize
-from fluent.syntax.ast import Message, TextElement, Identifier, Pattern, Junk
-
-core = "../../../anki-i18n/core/core"
-qt = "../../../anki-i18n/qtftl/desktop"
-
-qt_modules = {"about", "qt-accel", "addons", "qt-misc"}
-
-modules = json.load(open("strings_by_module.json"))
-translations = json.load(open("strings.json"))
-
-# # fixme:
-# addons addons-downloaded-fnames Downloaded %(fname)s
-# addons addons-downloading-adbd-kb02fkb Downloading %(a)d/%(b)d (%(kb)0.2fKB)...
-# addons addons-error-downloading-ids-errors Error downloading %(id)s: %(error)s
-# addons addons-error-installing-bases-errors Error installing %(base)s: %(error)s
-# addons addons-important-as-addons-are-programs-downloaded Important: As add-ons are programs downloaded from the internet, they are potentially malicious.You should only install add-ons you trust.
Are you sure you want to proceed with the installation of the following Anki add-on(s)?
%(names)s
-# addons addons-installed-names Installed %(name)s
-# addons addons-the-following-addons-are-incompatible-with The following add-ons are incompatible with %(name)s and have been disabled: %(found)s
-# card-templates card-templates-delete-the-as-card-type-and Delete the '%(a)s' card type, and its %(b)s?
-# browsing browsing-found-as-across-bs Found %(a)s across %(b)s.
-# browsing browsing-nd-names %(n)d: %(name)s
-# importing importing-rows-had-num1d-fields-expected-num2d '%(row)s' had %(num1)d fields, expected %(num2)d
-# about about-written-by-damien-elmes-with-patches Written by Damien Elmes, with patches, translation, testing and design from:
%(cont)s
-# media media-recordingtime Recording...
Time: %0.1f
-# addons-unknown-error = Unknown error: {}
-
-# fixme: isolation chars
-
-
-def transform_text(text: str) -> str:
- # fixme: automatically remap to %s in a compat wrapper? manually fix?
- text = (
- text.replace("%d", "{ $val }")
- .replace("%s", "{ $val }")
- .replace("{}", "{ $val }")
- )
- if "Clock drift" in text:
- text = text.replace("\n", "
")
- else:
- text = text.replace("\n", " ")
- return text
-
-
-def check_parses(path: str):
- # make sure the file parses
- with open(path) as file:
- orig = file.read()
- obj = parse(orig)
- for ent in obj.body:
- if isinstance(ent, Junk):
- raise Exception(f"file had junk! {path} {ent}")
-
-
-for module, items in modules.items():
- if module in qt_modules:
- folder = qt
- else:
- folder = core
-
- if not module.startswith("statistics"):
- continue
-
- # templates
- path = os.path.join(folder, "templates", module + ".ftl")
- print(path)
- with open(path, "a", encoding="utf8") as file:
- for (key, text) in items:
- text2 = transform_text(text)
- file.write(f"{key} = {text2}\n")
-
- check_parses(path)
-
- # translations
- for (lang, map) in translations.items():
- if lang == "en":
- continue
-
- out = []
- for (key, text) in items:
- if text in map:
- out.append((key, transform_text(map[text])))
-
- if out:
- path = os.path.join(folder, lang, module + ".ftl")
- dir = os.path.dirname(path)
- if not os.path.exists(dir):
- os.mkdir(dir)
-
- print(path)
- with open(path, "a", encoding="utf8") as file:
- for (key, text) in out:
- file.write(f"{key} = {text}\n")
-
- check_parses(path)
diff --git a/repos.bzl b/repos.bzl
index 3de5f93b1..37f03f868 100644
--- a/repos.bzl
+++ b/repos.bzl
@@ -126,9 +126,6 @@ def register_repos():
qtftl_i18n_commit = "9909cfa4386288e686b2336b3b1048b7ee1bb194"
qtftl_i18n_shallow_since = "1605664969 +1000"
- qtpo_i18n_commit = "872d7f0f6bde52577e8fc795dd85699b0eeb97d5"
- qtpo_i18n_shallow_since = "1605564627 +0000"
-
i18n_build_content = """
filegroup(
name = "files",
@@ -166,15 +163,3 @@ exports_files(["l10n.toml"])
shallow_since = qtftl_i18n_shallow_since,
remote = "https://github.com/ankitects/anki-desktop-ftl",
)
-
- new_git_repository(
- name = "aqt_po",
- build_file_content = """
-exports_files(glob(["**/*.pot", "**/*.po"]),
-visibility = ["//visibility:public"],
-)
- """,
- commit = qtpo_i18n_commit,
- shallow_since = qtpo_i18n_shallow_since,
- remote = "https://github.com/ankitects/anki-desktop-i18n",
- )
diff --git a/run b/run
index 422e9fcab..c5cdaa5be 100755
--- a/run
+++ b/run
@@ -11,7 +11,7 @@ run_mac() {
# so we need to copy the files into a working folder before running on a Mac.
workspace=$(dirname $0)
bazel build //qt:runanki && \
- rsync -avPL --exclude=anki/external --exclude=__pycache__ --delete \
+ rsync -aiL --no-times --exclude=anki/external --exclude=__pycache__ --delete \
$workspace/bazel-bin/qt/runanki* $workspace/bazel-copy/ && \
$workspace/bazel-copy/runanki $*
}
diff --git a/qt/po/scripts/duplicate-string.py b/scripts/duplicate-string.py
similarity index 100%
rename from qt/po/scripts/duplicate-string.py
rename to scripts/duplicate-string.py