Skip to content

Commit 58b111d

Browse files
authored
Merge pull request #8608 from jepler/add-locale-module
Add `locale.getlocale()`
2 parents 1b9f0d5 + 43e7fcb commit 58b111d

File tree

9 files changed

+106
-7
lines changed

9 files changed

+106
-7
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ pseudoxml:
227227
all-source:
228228

229229
locale/circuitpython.pot: all-source
230-
find $(TRANSLATE_SOURCES) -type d \( $(TRANSLATE_SOURCES_EXC) \) -prune -o -type f \( -iname "*.c" -o -iname "*.h" \) -print | (LC_ALL=C sort) | xgettext -f- -L C -s --add-location=file --keyword=MP_ERROR_TEXT -o - | sed -e '/"POT-Creation-Date: /d' > $@
230+
find $(TRANSLATE_SOURCES) -type d \( $(TRANSLATE_SOURCES_EXC) \) -prune -o -type f \( -iname "*.c" -o -iname "*.h" \) -print | (LC_ALL=C sort) | xgettext -x locale/synthetic.po -f- -L C -s --add-location=file --keyword=MP_ERROR_TEXT -o - | sed -e '/"POT-Creation-Date: /d' > $@
231231

232232
# Historically, `make translate` updated the .pot file and ran msgmerge.
233233
# However, this was a frequent source of merge conflicts. Weblate can perform

locale/synthetic.po

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Localization of the locale name is done automagically
2+
msgid "en_US"
3+
msgstr ""
4+
5+
# This string should never be translated, but for technical reasons it has to appear as an MP_ERROR_TEXT
6+
msgid "%S"
7+
msgstr ""
8+
9+
# This string should never be translated, but for technical reasons it has to appear as an MP_ERROR_TEXT
10+
msgid "%q"
11+
msgstr ""
12+
13+
# This string should never be translated, but for technical reasons it has to appear as an MP_ERROR_TEXT
14+
msgid "%s"
15+
msgstr ""

ports/unix/variants/coverage/mpconfigvariant.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ SRC_BITMAP := \
3333
shared-bindings/audiomixer/MixerVoice.c \
3434
shared-bindings/bitmaptools/__init__.c \
3535
shared-bindings/displayio/Bitmap.c \
36+
shared-bindings/locale/__init__.c \
3637
shared-bindings/rainbowio/__init__.c \
3738
shared-bindings/struct/__init__.c \
3839
shared-bindings/synthio/__init__.c \
@@ -82,6 +83,7 @@ CFLAGS += \
8283
-DCIRCUITPY_DISPLAYIO_UNIX=1 \
8384
-DCIRCUITPY_FUTURE=1 \
8485
-DCIRCUITPY_GIFIO=1 \
86+
-DCIRCUITPY_LOCALE=1 \
8587
-DCIRCUITPY_OS_GETENV=1 \
8688
-DCIRCUITPY_RAINBOWIO=1 \
8789
-DCIRCUITPY_STRUCT=1 \

py/circuitpy_defns.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ endif
239239
ifeq ($(CIRCUITPY_KEYPAD),1)
240240
SRC_PATTERNS += keypad/%
241241
endif
242+
ifeq ($(CIRCUITPY_LOCALE),1)
243+
SRC_PATTERNS += locale/%
244+
endif
242245
ifeq ($(CIRCUITPY_MATH),1)
243246
SRC_PATTERNS += math/%
244247
endif
@@ -544,6 +547,7 @@ $(filter $(SRC_PATTERNS), \
544547
displayio/Colorspace.c \
545548
fontio/Glyph.c \
546549
imagecapture/ParallelImageCapture.c \
550+
locale/__init__.c \
547551
math/__init__.c \
548552
microcontroller/ResetReason.c \
549553
microcontroller/RunMode.c \

py/circuitpy_mpconfig.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,9 @@ CFLAGS += -DCIRCUITPY_KEYPAD_KEYMATRIX=$(CIRCUITPY_KEYPAD_KEYMATRIX)
320320
CIRCUITPY_KEYPAD_SHIFTREGISTERKEYS ?= $(CIRCUITPY_KEYPAD)
321321
CFLAGS += -DCIRCUITPY_KEYPAD_SHIFTREGISTERKEYS=$(CIRCUITPY_KEYPAD_SHIFTREGISTERKEYS)
322322

323+
CIRCUITPY_LOCALE ?= $(CIRCUITPY_FULL_BUILD)
324+
CFLAGS += -DCIRCUITPY_LOCALE=$(CIRCUITPY_LOCALE)
325+
323326
CIRCUITPY_MATH ?= 1
324327
CFLAGS += -DCIRCUITPY_MATH=$(CIRCUITPY_MATH)
325328

py/maketranslationdata.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ def translate(translation_file, i18ns):
9292
unescaped = original
9393
for s in C_ESCAPES:
9494
unescaped = unescaped.replace(C_ESCAPES[s], s)
95-
translation = table.gettext(unescaped)
95+
if original == "en_US":
96+
translation = table.info()["language"]
97+
else:
98+
translation = table.gettext(unescaped)
9699
# Add in carriage returns to work in terminals
97100
translation = translation.replace("\n", "\r\n")
98101
translations.append((original, translation))

shared-bindings/locale/__init__.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* SPDX-FileCopyrightText: Copyright (c) 2023 Jeff Epler for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "py/obj.h"
28+
#include "py/objtuple.h"
29+
30+
//| """Locale support module"""
31+
//|
32+
//| def getlocale() -> None:
33+
//| """Returns the current locale setting as a tuple ``(language code, "utf-8")``
34+
//|
35+
//| The language code comes from the installed translation of CircuitPython, specifically the "Language:" code specified in the translation metadata.
36+
//| This can be useful to allow modules coded in Python to show messages in the user's preferred language.
37+
//|
38+
//| Differences from CPython: No ``LC_*`` argument is permitted.
39+
//| """
40+
//|
41+
STATIC mp_obj_t getlocale(void) {
42+
43+
mp_rom_error_text_t locale_msg = MP_ERROR_TEXT("en_US");
44+
size_t len_with_nul = decompress_length(locale_msg);
45+
size_t len = len_with_nul - 1;
46+
char buf[len_with_nul];
47+
decompress(locale_msg, buf);
48+
49+
mp_obj_t elements[] = {
50+
mp_obj_new_str(buf, len),
51+
MP_OBJ_NEW_QSTR(MP_QSTR_utf_hyphen_8)
52+
};
53+
return mp_obj_new_tuple(MP_ARRAY_SIZE(elements), elements);
54+
}
55+
MP_DEFINE_CONST_FUN_OBJ_0(getlocale_obj, getlocale);
56+
57+
STATIC const mp_rom_map_elem_t locale_module_globals_table[] = {
58+
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_locale) },
59+
{ MP_ROM_QSTR(MP_QSTR_getlocale), MP_ROM_PTR(&getlocale_obj) },
60+
};
61+
62+
STATIC MP_DEFINE_CONST_DICT(locale_module_globals, locale_module_globals_table);
63+
64+
const mp_obj_module_t locale_module = {
65+
.base = { &mp_type_module },
66+
.globals = (mp_obj_dict_t *)&locale_module_globals,
67+
};
68+
69+
MP_REGISTER_MODULE(MP_QSTR_locale, locale_module);

tests/unix/extra_coverage.py.exp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,11 @@ audiomixer binascii bitmaptools cexample
5656
cmath collections cppexample displayio
5757
errno example_package gc
5858
hashlib heapq io json
59-
math os platform qrio
60-
rainbowio random re select
61-
struct synthio sys time
62-
traceback uctypes ulab zlib
59+
locale math os platform
60+
qrio rainbowio random re
61+
select struct synthio sys
62+
time traceback uctypes ulab
63+
zlib
6364
me
6465

6566
rainbowio random

tools/check_translations.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
template_filename = sys.argv[1]
1414
po_filenames = sys.argv[2:]
1515

16+
synthetic = polib.pofile("locale/synthetic.po")
17+
synthetic_ids = set([x.msgid for x in synthetic])
1618
template = polib.pofile(template_filename)
17-
all_ids = set([x.msgid for x in template])
19+
all_ids = set([x.msgid for x in template]) - synthetic_ids
1820
for po_filename in po_filenames:
1921
print("Checking", po_filename)
2022
po_file = polib.pofile(po_filename)

0 commit comments

Comments
 (0)