Projects/kdelibs/localisation
A page to document improvements to the localisation and internationalisation of KDE.
ISO 4217 Currency Code Support
I want to propose improving the KLocale currency support to fully support the ISO 4217 Currency Code standard. The existing currency support is minimal with each Locales .desktop file holding a currency symbol, the number of decimal places, and various display formating rules. This leaves applications such as KSpread, KMyMoney, Skrooge, Kraft, KEuroCalc, and various other financial and currency conversion programs and widgets to currently supply their own implementation of the ISO codes and translations of the names. This proposal will reduce duplication and improve flexability.
This proposal has the following primary objectives:
- To reduce duplication of translations of the currency names
- To improve localisation of currency and number formatting
- To improve consistancy across KDE apps in use of currency codes, names, and formats
- To simplify user configuration options
- To operate in a consistent fashion with other desktops and platforms to enable later standardisation of KLocale across all platforms
A single Currency Code may be used in multiple Locales, and a Locale can use multiple Currencies i.e. a Many-to-Many relationship, not the 1-to-1 we currently support. This proposal is to separate each Currency Code into a new .desktop file holding the fundamental and constant details. The Locale .desktop file will only hold a list of associated Currency Codes and a default Money Format, with the user able to override the default Currency Code and Money Format.
This is essentially the same way Languages are currently catered for.
There are a number of outstanding issues I welcome comment on, in particular around translation issues. This is an initial proposal aimed at improving the l10n and i18n issues. There may be future scope for adding functions such as standard rounding or conversion routines and settlement dates, but these may better belong in the proposed kdefinancial module. Comment on this is welcome especially from the apps who would be using it.
Currency Code file
The following fields will be stored in the *.desktop file for each Currency. See outstanding issues for naming/location of the *.desktop file.
FieldName=example [rule]
CurrencyCodeIsoAlpha3=NZD [required]
- Alpha form of ISO Currency Code. Key field in spite of localisation issues. Not translated, do we need to provide a translated version in a separate field/method?
CurrencyCodeIsoNumeric3=554 [required]
- Numeric form of ISO Currency Code, always 3 digits long with leading 0's if required, so stored/returned as a string. This format is free of localisation issues inherent in any alpha code.
CurrencyNameIso=New Zealand Dollar [required]
- Official ISO Name of Currency. See outstanding issues. Translated?
CurrencyNameDisplay=New Zealand Dollar [default=CurrencyNameIso]
- Display formatted name of Currency in capitalised <Adjectival Locale> <Currency Name> format. See outstanding issues. Translated.
CurrencyUnitSymbols=$,NZ$,NZD [required]
- List of valid symbols for currency units, to allow user to choose preferred option. Usually made up of Default, Unambiguous, and ISO Code, plus any other local variations. Translated?
CurrencyUnitSymbolDefault=$ [required]
- Default symbol for currency units as defined by ISO standard, can be a non-standard glyph or a combination of multiple glyphs. Only 1 glyph known not to exist in Unicode which is commonly replaced with a letter (see AZN). Translated?
CurrencyUnitSymbolUnambiguous=NZ$ [default=CurrencyUnitSymbol]
- Unambiguous symbol for currency units. Cater for displaying multiple currencies that use the same symbol, e.g. USD, AUD, NZD all use $, the unambiguous forms are US$, AU$, NZ$. Default to blank and return CurrencyUnitSymbolDefault if unambiguous. Normally expect apps to show locale currency with default/ambiguous symbol and foreign currencies with unambiguous, but provide user setting to choose to always show unambiguous for locale currency. Translated?
CurrencyUnitSingular=dollar [required]
- Name of currency unit in English singular form. Translated.
CurrencyUnitPlural=dollars [required]
- Name of currency unit in English plural form. Translated.
CurrencySubunitSymbol=c [default=""]
- Symbol used for subunit, blank if no official symbol. Not translated?
CurrencySubunitSingular=cent [required]
- Name of currency subunit in English singular form. Translated.
CurrencySubunitPlural=cents [required]
- Name of currency subunit in English plural form. Translated.
CurrencyActive=true [default=true]
- If currency is Active or Obsolete.
CurrencyIntroducedDate=1967,07,10 [default=QDate()]
- Date currency introduced, blank if unknown
CurrencyWithdrawnDate= [default=QDate()]
- Date currency withdrawn, blank if still active
CurrencyDecimal=true [default=true]
- If this is a decimal or non-decimal currency, i.e. if CurrencySubunitsPerUnit is a multiple of 10. There are some non-decimal currencies, e.g. 5 subunits to the unit. No public API, for internal use only. Could just test CurrencySubunitsPerUnit instead?
CurrencySubunits=1 [default=1]
- Number of subunits currency has, e.g. Yuan = 2. No public API, for internal use only. See also outstanding issues.
CurrencySubunitsInCirculation=true [default=true]
- If the Subunits are actually in use, or no longer in circulation. Useful when still need subunits formatted in display strings but not able to be entered as not in use.
CurrencySubunitsPerUnit=100 [default=100]
- Will be 0 for Currencies with no Subunits. Will be populated > 0 but with CurrencySubunitsInCirculation=false for those currencies that have a Subunit no longer in circulation. Note is different to CurrencyDecimalPlaces as there are some non-decimal currencies, e.g. 5 subunits to the unit.
CurrencyDecimalPlacesDisplay=2 [default=2]
- The number of decimal places required to display all subunits. Normally the same as 1/CurrencySubunitsPerUnit except for non-decimal currencies, and multiple subunit currencies where smallest subunit is not the supported subunit (e.g. Yuan). Use as default for locale MonetaryDecimalPlacesDisplay.
CurrencyCountriesInUse=NZ,CK,NU,PN,TK [required]
- List of the countries known to be using the currency. Keep issuing country as first in list, but some currencies are issued by supra-national bodies (e.g. EU) so do not rely on this. Note this may be official or unofficial use.
KCurrency class
See diff for initial proposal. Comment welcomed on how useful this will be for applications, as I notice that most use a more generic Unit class with Currency a special case.
System Locale file
The Country i10n *.desktop file will have the following fields added:
CurrencyCodesInUse=USD,EUR,GBP [required]
- List of default Currency Codes used in the Locale.
CurrencyCode=USD [required]
- Current default Currency Code used in the Locale.
DecimalPlaces=2 [default=2]
- Number of deciaml places for numbers only.
MonetaryDecimalPlaces=2 [default=2]
- Number of deciaml places for money only.
The following fields will be deleted:
FracDigits
- Replaced by DecimalPlaces and MonetaryDecimalPlaces.
CurrencySymbol
- Replaced by CurrencyCodes.
User Locale file
DecimalPlaces
- User override for Locale file value only if entered in KCM.
MonetaryDecimalPlaces
- User override for Locale file value only if entered in KCM.
FracDigits
- Any user override value for FracDigits will be automatically transferred to DecimalPlaces and MonetaryDecimalPlaces and then FracDigits will be deleted.
CurrencySymbol
- On conversion, ignore and delete as no reliable conversion process. How to do conversion???. After conversion read and use if populated otherwise use default. In KCM populate if user selects symbol other than default.
KLocale changes
The following functions will be added based on their Country/Language analogs:
currency()
- Returns a KCurrency for the current locale Currency Code to enable access to names, etc.
currencyCode()
- Returns CurrencyCode, i.e, current locale Currency Code
setCurrencyCode(QString)
- Set the Currency Code for the locale
defaultCurrencyCode()
- USD I guess
allCurrencyCodesList()
- Returns all ISO Currency Codes available in KDE
currencyCodeToName(QString)
- Return localised name of currency requested
decimalPlaces()
- Applies to numbers only, not money, default to 2
setDecimalPlaces(int)
- Applies to numbers only, not money
moneyDecimalPlaces()
- Applies to money only, default to CurrencyDecimalPlacesDisplay
setMoneyDecimalPlaces(int)
- Applies to money only
Modified:
formatNumber()
- Use decimalPlaces() instead of 2
formatMoney()
- Use decimalPlaces() instead of fracDigits()
Deprecated:
fracDigits()
- Point to monetaryDecimalPlaces()
setFracDigits(int)
- Point to setMonetaryDecimalPlaces()? Or noop?
System Settings changes
Region/Numbers Tab:
- Add Decimal Places
Region/Money Tab:
- Add combo to list all currencies, with default currencies for country listed at top
- Change 'Currency Symbol' free text input to combo listing all valid symbols for currently selected currency
- Change 'Fract Digits' to 'Decimal Places'
Open questions
SVN & Install Location/Filenames
- How to name where to locate new desktop files?
- Save all .desktop files in a single folder with format <isocode>.desktop, or in subfolder as in country codes? Subfolders useful only if other resources added, like symbol image, but naming scheme would make that redundent? Less work too.
- Cannot put into kdebase/runtime/l10n/ as KLocale implementation relies on reading names of files and subfolders in there, would like to svn move into kdebase/runtime/localization/l10n instead but still install to ${LOCALE_INSTALL_DIR}/l10n.
Conclusion: SVN kdebase/runtime/localization/currency/<isocode>.desktop. Install to ${LOCALE_INSTALL_DIR}/currency
Multiple subunits
- Some currencies have more than one subunit, should we support this?
- CNY Chinese yuan = jiao 1/10, fen 1/100, only jiao in much use
- EGP Egyptian pound = qirsh/piastre 1/100 , maleem/millieme 1/1000, only qirsh/piastre in circulation
- HKD Hong Kong dollar = 1/10 ho, 1/100 cent/sin, coins denominated in cents
- JOD Jordanian dinar = dirham 1/10, qirsh/piastre 1/100, fils 1/1000, only qirsh/piastre in current use
- JPY Japanese yen = 1/100 sen, 1/1000 rin, neither in current use
- KHR Cambodian riel = 1/10 kak, 1/100 sen, neither in current use
- MOP Macanese pataca = 1/10 ho, 1/100 avo/sin, only ho in use
- USD US dollar = dime 1/10, cent 1/100, and mill 1/1000, cent in most common use, mill for accounting only, dime common use but redundant
- VND Vietmanese Dong = 1/10 hào and 1/100 xu, neither in current use
- Makes for lots of issues with display and input formats, would need major changes to gui widgets.
- Not worth it given each only has one or none subunit in active use?
- Display field would be easier to support as is just a formatted string, but entry fields would be harder, may be a reason to have separate input and display formats?
Conclusion: Use active subunit, and have CurrencyDisplayDecimalPlaces for when active subunit bigger than smallest subunit.
Include Precious Metals and other Financial Instruments
- The ISO standard also includes codes for some Precious Metals and other Financial Instruments,should we include these in our support?
- Metals include XPD Palladium, XAU Gold, etc
- Financial instruments include XFU International Union of Railways Franc, XDR IMF Special Drawing Rights, etc
- If included should we derive KCurrency from a more generic KFinancialUnit? Would then need a UnitType enum.
Translations / Plurals, etc
- How to deal with plurals and translations, and what to translate?
- Separate fields/methods for singular and plural? What to supply for others like nom/gen forms? If currency has no plural form, leave field blank and default to singular, or put singular in field?
- Which names and symbols to translate? e.g. include both Arabic and Latin forms of symbol in list, or only Latin and leave Arabic form for translation? Is it likely user would want English desktop with Arabic symbol, or vv?
- Do we provide both untranslated and translated versions of the ISO Code, i.e. would an Arabic user write the code as USD or something in Arabic?
- What needs to be done to hook into scripty?
ISO name vs Formatted Name
- The formal ISO name is very inconsistant
- Sometimes just the Unit Name when unique (Lek)
- Sometimes the country and unit when unit not unique (Argentine Peso)
- Sometimes something else at the countries request or common usage (Pound Sterling)
- Sometimes even in the countries native language instead of English (Peso Uruguayo)
- This is not usable in a picklist for users, a consistantly formatted name of <Country> <Unit> could be more user friendly.
- Should we support one or other, or both? Both would lead to more work for translators, but a large part would be duplication.
- Also capitalisation: 'Lek' vs 'lek' vs 'Albanian Lek' vs 'Albanian lek'?
- Should the official ISO name even be translated?
Conclusion: Provide separate ISO Name and Label forms, both translated, when the same only populate the ISO field and use for display.
User override Currency Symbol
- Should we allow the user to set their own Currency Symbol to replace the default one for their chosen currency?
- We only allowed this before as it was the whole means of setting the currency.
- If we allow then could enter a symbol not valid for the chosen currency, e.g. have symbol of $ but currency of EUR.
- How to do one-off conversion?
Conclusion: Ability to choose from list of standard symbols should be enough flexibility. Can be manually overridden in users locale file if really needed. If major backlash can allow free text entry in combo.
Correct number grouping
- Some countries have different grouping sizes instead of by thousands (000 000 000.00).
- Chinese & Japanese group by 4 (0000 0000 0000.00)
- India by 2 with 3 in the smallest group (00 00 00 000.00).
Conclusion: We should cater for this by implementing grouping support as per LC_NUMERIC and LC_MONETARY formats. Look to add support later once Currency Code change completed.
Not supported
Separate Display and Input formats
Allow format and read methods to use separate input and output format strings. No-one else supports, low priority for now.
Plural forms of Currency Symbols
SZL Swazi lilangeni and LSL Lesotho loti have singular and plural currency symbols, e.g. LSL has Loti/Maloti so L/M, so L1, M2, M3, etc. No support for now as unique. Perhaps translation can help here?
Note and coin denominations in circulation
Not enough apps would need this information, and it would be a burden to maintain. A POS app may want to know this, and perhaps a currency converter.
Superunits
When multiples of the main unit are named. This might be useful if obsolete currencies supported, otherwise no-one officially supports these now?
- Iranian toman (10) common but unofficial
- Pakistani lakh (100,000) and crore (10,000,000) common in English but unofficial
- Japanese man (10,000) common but unofficial
Meta-info
Could later add meta-info like Convertible, Floating, Fixed, Pegged, etc.
Rounding Rules
Locales and Currencies may have different rounding rules to be applied in basic maths or conversion processes. These are considered out of scope for now but may be introduced later. This will require input form the financial apps.