2018-07-23 11:35:38 +00:00
|
|
|
/** @file */
|
2018-05-22 01:20:03 +00:00
|
|
|
//language.h
|
2016-07-22 13:28:01 +00:00
|
|
|
#ifndef LANGUAGE_H
|
|
|
|
#define LANGUAGE_H
|
|
|
|
|
2018-06-21 17:58:13 +00:00
|
|
|
|
2018-05-22 01:20:03 +00:00
|
|
|
#include "config.h"
|
2020-09-11 13:12:49 +00:00
|
|
|
#include "macros.h"
|
2018-05-30 17:29:52 +00:00
|
|
|
#include <inttypes.h>
|
2020-01-31 13:47:44 +00:00
|
|
|
#ifdef DEBUG_SEC_LANG
|
|
|
|
#include <stdio.h>
|
|
|
|
#endif //DEBUG_SEC_LANG
|
2018-05-22 01:20:03 +00:00
|
|
|
|
2016-07-22 13:28:01 +00:00
|
|
|
#define PROTOCOL_VERSION "1.0"
|
|
|
|
|
2018-06-07 22:20:28 +00:00
|
|
|
#ifndef CUSTOM_MENDEL_NAME
|
2016-07-22 13:28:01 +00:00
|
|
|
#define MACHINE_NAME "Mendel"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef MACHINE_UUID
|
|
|
|
#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
|
|
|
|
#endif
|
|
|
|
|
2018-05-22 01:20:03 +00:00
|
|
|
#if (LANG_MODE == 0) //primary language only
|
2018-10-23 15:32:52 +00:00
|
|
|
#define PROGMEM_I2 __attribute__((section(".progmem0")))
|
|
|
|
#define PROGMEM_I1 __attribute__((section(".progmem1")))
|
|
|
|
#define PROGMEM_N1 __attribute__((section(".progmem2")))
|
2018-05-22 01:20:03 +00:00
|
|
|
#define _I(s) (__extension__({static const char __c[] PROGMEM_I1 = s; &__c[0];}))
|
|
|
|
#define ISTR(s) s
|
|
|
|
#define _i(s) _I(s)
|
|
|
|
#define _T(s) s
|
2022-02-27 20:29:58 +00:00
|
|
|
#define _O(s) s
|
2018-05-22 01:20:03 +00:00
|
|
|
#else //(LANG_MODE == 0)
|
2018-10-23 15:32:52 +00:00
|
|
|
// section .loc_sec (originaly .progmem0) will be used for localized translated strings
|
|
|
|
#define PROGMEM_I2 __attribute__((section(".loc_sec")))
|
|
|
|
// section .loc_pri (originaly .progmem1) will be used for localized strings in english
|
|
|
|
#define PROGMEM_I1 __attribute__((section(".loc_pri")))
|
|
|
|
// section .noloc (originaly progmem2) will be used for not localized strings in english
|
|
|
|
#define PROGMEM_N1 __attribute__((section(".noloc")))
|
2018-05-30 13:07:24 +00:00
|
|
|
#define _I(s) (__extension__({static const char __c[] PROGMEM_I1 = "\xff\xff" s; &__c[0];}))
|
2018-05-30 12:53:14 +00:00
|
|
|
#define ISTR(s) "\xff\xff" s
|
2018-05-22 01:20:03 +00:00
|
|
|
#define _i(s) lang_get_translation(_I(s))
|
|
|
|
#define _T(s) lang_get_translation(s)
|
2022-02-27 20:29:58 +00:00
|
|
|
#define _O(s) (s + 2)
|
2018-05-22 01:20:03 +00:00
|
|
|
#endif //(LANG_MODE == 0)
|
|
|
|
#define _N(s) (__extension__({static const char __c[] PROGMEM_N1 = s; &__c[0];}))
|
|
|
|
#define _n(s) _N(s)
|
|
|
|
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @brief lang_table_header_t structure - (size= 16byte) */
|
2018-06-07 22:20:28 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint32_t magic; //+0
|
|
|
|
uint16_t size; //+4
|
|
|
|
uint16_t count; //+6
|
|
|
|
uint16_t checksum; //+8
|
|
|
|
uint16_t code; //+10
|
2018-06-15 18:37:33 +00:00
|
|
|
uint32_t signature; //+12
|
2018-06-07 22:20:28 +00:00
|
|
|
} lang_table_header_t;
|
|
|
|
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @brief lang_table_t structure - (size= 16byte + 2*count) */
|
2018-06-07 22:20:28 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
lang_table_header_t header;
|
|
|
|
uint16_t table[];
|
|
|
|
} lang_table_t;
|
2018-05-22 01:20:03 +00:00
|
|
|
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @name Language indices into their particular symbol tables.*/
|
|
|
|
///@{
|
2018-05-28 15:14:55 +00:00
|
|
|
#define LANG_ID_PRI 0
|
|
|
|
#define LANG_ID_SEC 1
|
2018-07-23 11:35:38 +00:00
|
|
|
///@}
|
2018-05-28 15:14:55 +00:00
|
|
|
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @def LANG_ID_FORCE_SELECTION
|
|
|
|
* @brief Language is not defined and it shall be selected from the menu.*/
|
2018-05-22 01:20:03 +00:00
|
|
|
#define LANG_ID_FORCE_SELECTION 254
|
2018-06-01 08:47:47 +00:00
|
|
|
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @def LANG_ID_UNDEFINED
|
|
|
|
* @brief Language is not defined on a virgin RAMBo board. */
|
2018-05-22 01:20:03 +00:00
|
|
|
#define LANG_ID_UNDEFINED 255
|
2016-07-22 13:28:01 +00:00
|
|
|
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @def LANG_ID_DEFAULT
|
|
|
|
* @brief Default language ID, if no language is selected. */
|
2018-05-28 15:14:55 +00:00
|
|
|
#define LANG_ID_DEFAULT LANG_ID_PRI
|
2016-07-22 13:28:01 +00:00
|
|
|
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @def LANG_MAGIC
|
|
|
|
* @brief Magic number at begin of lang table. */
|
2018-06-01 08:47:47 +00:00
|
|
|
#define LANG_MAGIC 0x4bb45aa5
|
|
|
|
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @name Language codes (ISO639-1)*/
|
|
|
|
///@{
|
|
|
|
#define LANG_CODE_XX 0x3f3f //!<'??'
|
|
|
|
#define LANG_CODE_EN 0x656e //!<'en'
|
|
|
|
#define LANG_CODE_CZ 0x6373 //!<'cs'
|
|
|
|
#define LANG_CODE_DE 0x6465 //!<'de'
|
|
|
|
#define LANG_CODE_ES 0x6573 //!<'es'
|
2018-10-25 16:16:36 +00:00
|
|
|
#define LANG_CODE_FR 0x6672 //!<'fr'
|
2018-07-23 11:35:38 +00:00
|
|
|
#define LANG_CODE_IT 0x6974 //!<'it'
|
|
|
|
#define LANG_CODE_PL 0x706c //!<'pl'
|
2021-12-20 16:32:35 +00:00
|
|
|
#ifdef COMMUNITY_LANGUAGE_SUPPORT //Community language support
|
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_NL
|
2021-03-01 07:22:43 +00:00
|
|
|
#define LANG_CODE_NL 0x6e6c //!<'nl'
|
2021-12-20 16:32:35 +00:00
|
|
|
#endif // COMMUNITY_LANG_GROUP1_NL
|
2021-12-21 13:33:35 +00:00
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_SV
|
|
|
|
#define LANG_CODE_SV 0x7376 //!<'sv'
|
|
|
|
#endif // COMMUNITY_LANG_GROUP1_SV
|
2022-02-22 10:56:01 +00:00
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_NO
|
|
|
|
#define LANG_CODE_NO 0x6E6F //!<'no'
|
|
|
|
#endif // COMMUNITY_LANG_GROUP1_NO
|
2021-12-21 14:15:23 +00:00
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_DA
|
|
|
|
#define LANG_CODE_DA 0x6461 //!<'da'
|
|
|
|
#endif // COMMUNITY_LANG_GROUP1_DA
|
2021-12-21 14:24:06 +00:00
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_SL
|
|
|
|
#define LANG_CODE_SL 0x736C //!<'sl'
|
|
|
|
#endif // COMMUNITY_LANG_GROUP1_SL
|
2021-12-21 14:28:33 +00:00
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_HU
|
|
|
|
#define LANG_CODE_HU 0x6875 //!<'hu'
|
|
|
|
#endif // COMMUNITY_LANG_GROUP1_HU
|
2021-12-21 14:32:54 +00:00
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_LB
|
|
|
|
#define LANG_CODE_LB 0x6C62 //!<'lb'
|
|
|
|
#endif // COMMUNITY_LANG_GROUP1_LB
|
2021-12-21 14:36:34 +00:00
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_HR
|
|
|
|
#define LANG_CODE_HR 0x6872 //!<'hr'
|
|
|
|
#endif // COMMUNITY_LANG_GROUP1_HR
|
2022-01-03 14:00:45 +00:00
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_LT
|
|
|
|
#define LANG_CODE_LT 0x6C74 //!<'lt'
|
|
|
|
#endif // COMMUNITY_LANG_GROUP1_LT
|
2022-02-10 18:01:04 +00:00
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_SK
|
|
|
|
#define LANG_CODE_SK 0x736b //!<'sk'
|
|
|
|
#endif // COMMUNITY_LANG_GROUP1_SK
|
2022-01-12 09:09:01 +00:00
|
|
|
#ifdef COMMUNITY_LANG_GROUP1_RO
|
|
|
|
#define LANG_CODE_RO 0x726F //!<'ro'
|
|
|
|
#endif // COMMUNITY_LANG_GROUP1_RO
|
2021-03-01 07:22:43 +00:00
|
|
|
//Use the 3 lines below as a template and replace 'QR', '0X7172' and 'qr'
|
2021-12-20 16:32:35 +00:00
|
|
|
//#ifdef COMMUNITY_LANG_GROUP1_QR
|
2021-03-01 07:22:43 +00:00
|
|
|
//#define LANG_CODE_QR 0x7172 //!<'qr'
|
2021-12-20 16:32:35 +00:00
|
|
|
//#endif // COMMUNITY_LANG_GROUP1_QR
|
|
|
|
#endif // COMMUNITY_LANGUAGE_SUPPORT
|
2018-07-23 11:35:38 +00:00
|
|
|
///@}
|
2016-07-22 13:28:01 +00:00
|
|
|
|
2018-05-22 01:20:03 +00:00
|
|
|
#if defined(__cplusplus)
|
|
|
|
extern "C" {
|
|
|
|
#endif //defined(__cplusplus)
|
|
|
|
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @brief Currectly active language selection.*/
|
2018-05-30 17:29:52 +00:00
|
|
|
extern uint8_t lang_selected;
|
2018-05-22 01:20:03 +00:00
|
|
|
|
2018-05-23 13:46:08 +00:00
|
|
|
#if (LANG_MODE != 0)
|
|
|
|
extern const char _SEC_LANG[LANG_SIZE_RESERVED];
|
2018-05-22 01:20:03 +00:00
|
|
|
extern const char* lang_get_translation(const char* s);
|
New PO-based language translation support (#3471)
* lang: Add a PO language extractor with FW metadata support
Implement a straight-to-po language extractor which supports our custom
language requirements:
- _i/_I/ISTR for text string definitions
- _T for catalog translations (with back-reference support)
- //// EOL comments with:
- MSG_ catalog entry name identifiers
- c=X r=Y annotations for screen dimensioning checks
- Crude support for commented lines
All source locations are correctly referenced in the PO, with the
metadata colleted in the comment for further processing.
Several checks are implemented already during extraction:
- Correct catalog name assignment (no duplicates)
- Metadata checks for each entry
Further checks will be implemented by directly checking the translated PO file.
Requires "polib" and "regex" python modules.
* lang: Adapt lang-check to work directly on PO/POT files
* lang: Allow lang-extract to generate stable (pre-sorted) output directly
* lang: Further extend lang-extract consistency/error checking
- Do not parse inside preprocessor conditionals
- Distinguish between references and definitions
- Warn about missing references and definitions
* lang: lang-extract: warn about incorrect PROGMEM assignments
Check that ISTR is used along with PROGMEM_I1 in an attempt to spot
useless translated catalogs.
* lang: lang-extract: Improved handling of same-line translations
Correctly reference metadata on same-line translations.
* lang: lang-extract: Handle _O as a cat-ref
https://github.com/prusa3d/Prusa-Firmware/pull/3434
* lang: lang-extract: Warn about unused catalog definitions
* lang: lang-extract: Allow propagating translation comments via //
The definition:
code //// definition [// comment]
will check [definition] as before, but blindly accumulate // comment.
The comment is then re-appended back into the PO files for translators
with the form:
definition
comment
comment...
* lang: Fix incorrect display definitions
* lang: lang-extract: Check source encoding/charmap
* lang: Translate the degree symbol
* lang: Unbreak/cleanup DEBUG_SEC_LANG
* lang: Improve meaning of comment
* lang: Split charset conversions into an aux lib for future use
* lang: Implement lang-map.py to extract the translation symbol map
- Extracts the translatable symbol map for further use
- Computes a stable "language signature" from the map itself
- Optionally patches the binary update the symbols
* lang: Check for translation recoding problems
* lang: Implement a transliteration map to post-process translations
TRANS_CHARS is now used to replace unavailable symbols to the source
encoding, only while producing the language catalog.
* lang: Handle/check character replacements in lang-check
Filter the translation through TRANS_CHARS, so that the preview and
length check are performed correctly for expanding replacements such as
'ß' to 'ss'.
* lang: Implement lang-build.py to generate the final language catalog
* Cleanup .gitignore
* lang: Drop txt language files
* lang: Remove outdated translation scripts and obsolete docs
* lang: Update build scripts for new infrastructure
* lang: [no] Integrate accents from po/new/no.po
We now support accents natively
* lang: Remove redundant directory po/new/
* lang: Fix encoding of LCD characters in PO files
* lang: [hr] Fix wrapping in MSG_CRASH_DET_ONLY_IN_NORMAL
* lang: Sort and reformat PO files for further massaging
* lang: Switch to developer (dot) comments for PO metadata
* lang: Allow the IGNORE annotation to skip extraction
* lang: Fix missing/broken language metadata in sources
* lang: Add update-pot.sh and regenerate po/Firmware.pot
* lang: Add update-po.sh and refresh all PO files
* lang: Add summary documentation about the new translation workflow
* Add more ignored files
* CI: Add new required dependencies to travis
* lang: lang-build: Improve warning message
"referenced" was really meaning that data is being duplicated.
* lang: Respect the language order as defined in config.sh
This correctly splits normal and community-made entries during language
selection.
* lang: More typos in the documentation
* lang: Check for the maximum size of each language
Each table needs to fit within LANG_SIZE_RESERVED
* lang: Properly align _SEC_LANG to page boundaries
... instead of relying on _SEC_LANG_TABLE to calculate the offset
* lang: Build support for dual-language hex files
Detect the printer type by checking the current variant type.
On printers with no xflash (MK2*), generate one hex file for each
additional language file by patching the built-in secondary language
table during the build process
* lang: Mention lang-patchsec.py
* lang: Use color() instead of tput for clarity
* lang: Allow disabling terminal colors with NO_COLOR/TERM=dumb
* lang: Consistent use of redirection in config.sh
* lang: Stricter variant-type check for xflash support
* lang: Output size stats when building double-language hex files
* lang: Respect NO_COLOR in lang-check.py
* lang: Check for repeated/incorrect annotations
Catch errors such as "c=1 c=2"
* lang: Correct MSG_SLIGHT_SKEW/MSG_SEVERE_SKEW annotations
* lang: [it] Improve MSG_*_SKEW translation
* lang: Use INTLHEX instead of OUTHEX_P/S for configuration
We already have OUTHEX which is the compiled firmware.
Use INTLHEX for the final internationalized firmware, which is less
confusing. Also, assume it being a prefix for all generated hex
files, which reduces the number of variables set.
* lang: Move lang_map to lib.io for further use
* lang: lang-check: Accept a firmware map file to suppress unused string warnings
* lang: Use the map file to reduce useless warnings during fw-build
* lang: lang-check: Also suppress unused empty annotations
* lang: Fix MSG_MOVE_CARRIAGE_TO_THE_TOP_Z annotation
Refresh pot file
* lang: lang-check: Do not warn about same-word translations by default
Do not warn when one-word translations such as "No" result in "No" also
in other languages, since this is common in latin languages.
Allow to re-enable the warning with --warn-same
* lang: lang-build: Handle same-source/translation efficiently
* lang: [it] Explicitly add On/Off/Reset/Wizard to suppress warnings
Instead of displaying a warning, supress the warning and explicitly
translate each entry using english (which is the common/acceptable
word in these cases).
* lang: [it] Suppress more warnings
* lang: lang-check: Add intermediate "suggest" warning category
Warnings in the "suggest" category as shown as [S] as based on pure
speculation from the checking tool, such as the translation being
significantly shorter than the original.
As a result, they can be suppressed with --no-suggest
* lang: Return translation status from lang-check
- 0 if the translation only contains suggestions
- 1 if the translation contains warnings or errors
Check for the exit status in fw-build.sh, but do nothing at the moment
except printing a non-fatal error.
* lang: Remove "trim_trailing_whitespace=false" for po files
PO files got cleaned up/rewritten. We can now ensure they stay
consistent.
* lang: [sv] Re-integrate changes from 70c73cb
* lang: [no] Reintegrate changes from @pkg2000
2022-06-16 13:03:30 +00:00
|
|
|
#define _SEC_LANG_TABLE ((uint16_t)&_SEC_LANG)
|
2018-06-07 22:20:28 +00:00
|
|
|
#endif //(LANG_MODE != 0)
|
|
|
|
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @brief selects language, eeprom is updated in case of success */
|
2018-06-07 22:20:28 +00:00
|
|
|
extern uint8_t lang_select(uint8_t lang);
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @brief performs checksum test of secondary language data */
|
2018-06-15 18:37:33 +00:00
|
|
|
extern uint8_t lang_check(uint16_t addr);
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @return total number of languages (primary + all in xflash) */
|
2018-06-10 14:04:32 +00:00
|
|
|
extern uint8_t lang_get_count(void);
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @brief reads lang table header and offset in xflash or progmem */
|
2018-06-08 23:23:04 +00:00
|
|
|
extern uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* offset);
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @brief reads lang code from xflash or progmem */
|
2018-06-01 08:47:47 +00:00
|
|
|
extern uint16_t lang_get_code(uint8_t lang);
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @return localized language name (text for menu item) */
|
2018-06-07 22:20:28 +00:00
|
|
|
extern const char* lang_get_name_by_code(uint16_t code);
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @brief reset language to "LANG_ID_FORCE_SELECTION", epprom is updated */
|
2018-06-10 14:04:32 +00:00
|
|
|
extern void lang_reset(void);
|
2018-07-23 11:35:38 +00:00
|
|
|
/** @retval 1 language is selected */
|
2018-06-10 14:04:32 +00:00
|
|
|
extern uint8_t lang_is_selected(void);
|
2018-05-30 18:15:43 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_SEC_LANG
|
2018-06-07 22:20:28 +00:00
|
|
|
extern const char* lang_get_sec_lang_str_by_id(uint16_t id);
|
2018-05-30 17:29:52 +00:00
|
|
|
extern uint16_t lang_print_sec_lang(FILE* out);
|
2018-05-30 18:15:43 +00:00
|
|
|
#endif //DEBUG_SEC_LANG
|
2018-05-22 01:20:03 +00:00
|
|
|
|
2018-06-09 22:22:28 +00:00
|
|
|
extern void lang_boot_update_start(uint8_t lang);
|
2018-06-09 17:16:36 +00:00
|
|
|
|
2018-05-22 01:20:03 +00:00
|
|
|
#if defined(__cplusplus)
|
|
|
|
}
|
|
|
|
#endif //defined(__cplusplus)
|
|
|
|
|
|
|
|
#define CAT2(_s1, _s2) _s1
|
|
|
|
#define CAT4(_s1, _s2, _s3, _s4) _s1
|
2018-05-28 15:14:55 +00:00
|
|
|
|
2018-05-22 01:20:03 +00:00
|
|
|
#include "messages.h"
|
2016-07-22 13:28:01 +00:00
|
|
|
|
2018-05-28 15:14:55 +00:00
|
|
|
|
2018-05-29 19:03:47 +00:00
|
|
|
#endif //LANGUAGE_H
|
2018-05-22 01:20:03 +00:00
|
|
|
|