locale-0.2.2/.gitignore01006440001750000175000000000022131121056570013156 0ustar0000000000000000target Cargo.lock locale-0.2.2/.travis.yml01006440001750000175000000003232131121056570013305 0ustar0000000000000000# TravisCI configuration based on https://github.com/japaric/trust # # We don't need binary build, only continuous integration, so we don't use # the deploy step. We also only build a somewhat representative selection of # targets. # Based on the "trust" template v0.1.1 # https://github.com/japaric/trust/tree/v0.1.1 dist: trusty language: rust services: docker sudo: required env: global: - CRATE_NAME=locale matrix: include: # Stable channel # Linux - env: TARGET=x86_64-unknown-linux-gnu - env: TARGET=i686-unknown-linux-gnu # OSX - env: TARGET=x86_64-apple-darwin os: osx # *BSD - env: TARGET=i686-unknown-freebsd DISABLE_TESTS=1 - env: TARGET=x86_64-unknown-netbsd DISABLE_TESTS=1 # Other architectures - env: TARGET=aarch64-unknown-linux-gnu - env: TARGET=armv7-unknown-linux-gnueabihf - env: TARGET=mips-unknown-linux-gnu - env: TARGET=mips64-unknown-linux-gnuabi64 - env: TARGET=mips64el-unknown-linux-gnuabi64 - env: TARGET=mipsel-unknown-linux-gnu - env: TARGET=powerpc-unknown-linux-gnu - env: TARGET=powerpc64-unknown-linux-gnu - env: TARGET=powerpc64le-unknown-linux-gnu - env: TARGET=s390x-unknown-linux-gnu DISABLE_TESTS=1 # Testing other channels - env: TARGET=x86_64-unknown-linux-gnu rust: nightly - env: TARGET=x86_64-apple-darwin os: osx rust: nightly before_install: set -e install: - sh ci/install.sh - source ~/.cargo/env || true script: - bash ci/script.sh after_script: set +e cache: cargo before_cache: # Travis can't cache files that are not readable by "others" - chmod -R a+r $HOME/.cargo # vim: set sw=2 sts=2: locale-0.2.2/Cargo.toml.orig01006440001750000175000000000711131121056570014062 0ustar0000000000000000[package] name = "locale" version = "0.2.2" description = "Library for basic localisation. Warning: Major rewrite pending for 0.3!" authors = [ "Ben S ", "Jan Hudec ", ] license = "MIT" documentation = "https://docs.rs/locale/" repository = "https://github.com/rust-locale/rust-locale/" readme = "README.md" keywords = ["i18n", "g12n", "l10n"] [dependencies] libc = "0.2" [package.metadata.release] upload-doc = true locale-0.2.2/Cargo.toml0000644000000016420007314 0ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "locale" version = "0.2.2" authors = ["Ben S ", "Jan Hudec "] description = "Library for basic localisation. Warning: Major rewrite pending for 0.3!" documentation = "https://docs.rs/locale/" readme = "README.md" keywords = ["i18n", "g12n", "l10n"] license = "MIT" repository = "https://github.com/rust-locale/rust-locale/" [dependencies.libc] version = "0.2" locale-0.2.2/Cargo.toml.orig0000644000000016330010253 0ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "locale" version = "0.2.2" authors = ["Ben S ", "Jan Hudec "] description = "Library for basic localisation. Warning: Major rewrite pending for 0.3!" documentation = "https://docs.rs/locale/" readme = "README.md" keywords = ["i18n", "g12n", "l10n"] license = "MIT" repository = "https://github.com/rust-locale/rust-locale/" [dependencies] libc = "0.2" locale-0.2.2/LICENSE01006440001750000175000000002132125000042160012164 0ustar0000000000000000The MIT License (MIT) Copyright (c) 2015 Ben S , Jan Hudec Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. locale-0.2.2/README.md01006440001750000175000000002176131121056570012461 0ustar0000000000000000[![TravisCI Build Status](https://travis-ci.org/rust-locale/rust-locale.svg?branch=master)](https://travis-ci.org/rust-locale/rust-locale) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/xb23rxc48wrmwq6q/branch/master?svg=true)](https://ci.appveyor.com/project/jan-hudec/rust-locale/branch/master) [![Crates.io Version](https://img.shields.io/crates/v/locale.svg)](https://crates.io/crates/locale) [![Docs.rs](https://docs.rs/locale/badge.svg)](https://docs.rs/locale/) # `rust-locale` **WORK IN PROGRESS** Will implement basic localization support. **Warning**: This version is mostly useless. Major rewrite is pending for version 0.3. ## Documentation On [![Docs.rs](https://docs.rs/locale/badge.svg)](https://docs.rs/locale/) or [github](https://rust-locale.github.io/rust-locale/rust-locale/). ## Installation It uses [Cargo](http://crates.io/), Rust's package manager. You can depend on this library by adding `locale` to your Cargo dependencies: ```toml [dependencies] locale = "0.2" ``` Or, to use the Git repo directly: ```toml [dependencies.locale] git = "https://github.com/rust-locale/rust-locale.git" ``` locale-0.2.2/appveyor.yml01006440001750000175000000002760131120742670013573 0ustar0000000000000000# AppVeyor configuration based on https://github.com/japaric/trust # # We don't need binary build, only continuous integration, so we don't use # the deploy step. We also only build subset of the configurations to keep # the time down. # Based on the "trust" template v0.1.1 # https://github.com/japaric/trust/tree/v0.1.1 environment: global: RUST_VERSION: stable CRATE_NAME: locale_config matrix: # MinGW - TARGET: i686-pc-windows-gnu - TARGET: x86_64-pc-windows-gnu # MSVC - TARGET: i686-pc-windows-msvc - TARGET: x86_64-pc-windows-msvc # Testing other channels - TARGET: x86_64-pc-windows-gnu RUST_VERSION: nightly - TARGET: i686-pc-windows-msvc RUST_VERSION: nightly install: - ps: >- If ($Env:TARGET -eq 'x86_64-pc-windows-gnu') { $Env:PATH += ';C:\msys64\mingw64\bin' } ElseIf ($Env:TARGET -eq 'i686-pc-windows-gnu') { $Env:PATH += ';C:\msys64\mingw32\bin' } - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - rustup-init.exe -y --default-host %TARGET% --default-toolchain %RUST_VERSION% - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - rustc -Vv - cargo -V test_script: - cargo build --target %TARGET% - cargo build --target %TARGET% --release - cargo test --target %TARGET% - cargo test --target %TARGET% --release cache: - C:\Users\appveyor\.cargo\registry - target # Building is done in the test phase, so we disable Appveyor's build phase. build: false # vim: set sw=2 sts=2: locale-0.2.2/ci/install.sh01006440001750000175000000001371131120742670013575 0ustar0000000000000000set -ex main() { local target= if [ $TRAVIS_OS_NAME = linux ]; then target=x86_64-unknown-linux-musl sort=sort else target=x86_64-apple-darwin sort=gsort # for `sort --sort-version`, from brew's coreutils. fi # This fetches latest stable release local tag=$(git ls-remote --tags --refs --exit-code https://github.com/japaric/cross \ | cut -d/ -f3 \ | grep -E '^v[0.1.0-9.]+$' \ | $sort --version-sort \ | tail -n1) curl -LSfs https://japaric.github.io/trust/install.sh | \ sh -s -- \ --force \ --git japaric/cross \ --tag $tag \ --target $target } main locale-0.2.2/ci/script.sh01006440001750000175000000000654131120742670013436 0ustar0000000000000000# This script takes care of testing your crate set -ex # TODO This is the "test phase", tweak it as you see fit main() { cross build --target $TARGET cross build --target $TARGET --release if [ ! -z $DISABLE_TESTS ]; then return fi cross test --target $TARGET cross test --target $TARGET --release } # we don't run the "test phase" when doing deploys if [ -z $TRAVIS_TAG ]; then main fi locale-0.2.2/examples/localeinfo.rs01006440001750000175000000023244131121056570015500 0ustar0000000000000000extern crate locale; #[cfg(target_os = "linux")] pub fn main() { use locale::linux::LibCLocaleFactory; use locale::linux::langinfo; use std::fmt::Debug; fn show<'a, T: langinfo::LanginfoItem<'a> + Debug>(f: &'a LibCLocaleFactory, i: T) { let j = f.langinfo(i); println!("{:?} = {:?}", i, j); } let f = LibCLocaleFactory::new("").unwrap(); show(&f, langinfo::_NL_COLLATE_CODESET); show(&f, langinfo::_NL_CTYPE_CODESET_NAME); show(&f, langinfo::_NL_MONETARY_CODESET); show(&f, langinfo::_NL_NUMERIC_CODESET); show(&f, langinfo::_NL_TIME_CODESET); show(&f, langinfo::_NL_MESSAGES_CODESET); show(&f, langinfo::_NL_PAPER_CODESET); show(&f, langinfo::_NL_NAME_CODESET); show(&f, langinfo::_NL_ADDRESS_CODESET); show(&f, langinfo::_NL_TELEPHONE_CODESET); show(&f, langinfo::_NL_MEASUREMENT_CODESET); show(&f, langinfo::_NL_IDENTIFICATION_CODESET); show(&f, langinfo::_NL_COLLATE_RULESETS); show(&f, langinfo::_NL_CTYPE_INDIGITS0_MB); show(&f, langinfo::_NL_CTYPE_INDIGITS1_MB); show(&f, langinfo::_NL_CTYPE_INDIGITS2_MB); show(&f, langinfo::_NL_CTYPE_INDIGITS3_MB); show(&f, langinfo::_NL_CTYPE_INDIGITS4_MB); show(&f, langinfo::_NL_CTYPE_INDIGITS5_MB); show(&f, langinfo::_NL_CTYPE_INDIGITS6_MB); show(&f, langinfo::_NL_CTYPE_INDIGITS7_MB); show(&f, langinfo::_NL_CTYPE_INDIGITS8_MB); show(&f, langinfo::_NL_CTYPE_INDIGITS9_MB); show(&f, langinfo::_NL_CTYPE_OUTDIGIT0_MB); show(&f, langinfo::_NL_CTYPE_OUTDIGIT1_MB); show(&f, langinfo::_NL_CTYPE_OUTDIGIT2_MB); show(&f, langinfo::_NL_CTYPE_OUTDIGIT3_MB); show(&f, langinfo::_NL_CTYPE_OUTDIGIT4_MB); show(&f, langinfo::_NL_CTYPE_OUTDIGIT5_MB); show(&f, langinfo::_NL_CTYPE_OUTDIGIT6_MB); show(&f, langinfo::_NL_CTYPE_OUTDIGIT7_MB); show(&f, langinfo::_NL_CTYPE_OUTDIGIT8_MB); show(&f, langinfo::_NL_CTYPE_OUTDIGIT9_MB); show(&f, langinfo::_NL_CTYPE_TRANSLIT_IGNORE); show(&f, langinfo::_NL_CTYPE_CLASS_NAMES); show(&f, langinfo::_NL_CTYPE_MAP_NAMES); show(&f, langinfo::INT_CURR_SYMBOL); show(&f, langinfo::CURRENCY_SYMBOL); show(&f, langinfo::MON_DECIMAL_POINT); show(&f, langinfo::MON_THOUSANDS_SEP); show(&f, langinfo::POSITIVE_SIGN); show(&f, langinfo::NEGATIVE_SIGN); show(&f, langinfo::_NL_MONETARY_CRNCYSTR); show(&f, langinfo::_NL_MONETARY_DUO_INT_CURR_SYMBOL); show(&f, langinfo::_NL_MONETARY_DUO_CURRENCY_SYMBOL); show(&f, langinfo::__DECIMAL_POINT); show(&f, langinfo::__THOUSANDS_SEP); show(&f, langinfo::ABDAY_1); show(&f, langinfo::ABDAY_2); show(&f, langinfo::ABDAY_3); show(&f, langinfo::ABDAY_4); show(&f, langinfo::ABDAY_5); show(&f, langinfo::ABDAY_6); show(&f, langinfo::ABDAY_7); show(&f, langinfo::DAY_1); show(&f, langinfo::DAY_2); show(&f, langinfo::DAY_3); show(&f, langinfo::DAY_4); show(&f, langinfo::DAY_5); show(&f, langinfo::DAY_6); show(&f, langinfo::DAY_7); show(&f, langinfo::ABMON_1); show(&f, langinfo::ABMON_2); show(&f, langinfo::ABMON_3); show(&f, langinfo::ABMON_4); show(&f, langinfo::ABMON_5); show(&f, langinfo::ABMON_6); show(&f, langinfo::ABMON_7); show(&f, langinfo::ABMON_8); show(&f, langinfo::ABMON_9); show(&f, langinfo::ABMON_10); show(&f, langinfo::ABMON_11); show(&f, langinfo::ABMON_12); show(&f, langinfo::MON_1); show(&f, langinfo::MON_2); show(&f, langinfo::MON_3); show(&f, langinfo::MON_4); show(&f, langinfo::MON_5); show(&f, langinfo::MON_6); show(&f, langinfo::MON_7); show(&f, langinfo::MON_8); show(&f, langinfo::MON_9); show(&f, langinfo::MON_10); show(&f, langinfo::MON_11); show(&f, langinfo::MON_12); show(&f, langinfo::AM_STR); show(&f, langinfo::PM_STR); show(&f, langinfo::D_T_FMT); show(&f, langinfo::D_FMT); show(&f, langinfo::T_FMT); show(&f, langinfo::T_FMT_AMPM); show(&f, langinfo::ERA_YEAR); show(&f, langinfo::ERA_D_FMT); show(&f, langinfo::ERA_D_T_FMT); show(&f, langinfo::ERA_T_FMT); show(&f, langinfo::_NL_TIME_ERA_ENTRIES); show(&f, langinfo::_NL_TIME_TIMEZONE); show(&f, langinfo::_DATE_FMT); show(&f, langinfo::ERA); show(&f, langinfo::ALT_DIGITS); show(&f, langinfo::YESEXPR); show(&f, langinfo::NOEXPR); show(&f, langinfo::YESSTR); show(&f, langinfo::NOSTR); show(&f, langinfo::_NL_NAME_NAME_FMT); show(&f, langinfo::_NL_NAME_NAME_GEN); show(&f, langinfo::_NL_NAME_NAME_MR); show(&f, langinfo::_NL_NAME_NAME_MRS); show(&f, langinfo::_NL_NAME_NAME_MISS); show(&f, langinfo::_NL_NAME_NAME_MS); show(&f, langinfo::_NL_ADDRESS_POSTAL_FMT); show(&f, langinfo::_NL_ADDRESS_COUNTRY_NAME); show(&f, langinfo::_NL_ADDRESS_COUNTRY_POST); show(&f, langinfo::_NL_ADDRESS_COUNTRY_AB2); show(&f, langinfo::_NL_ADDRESS_COUNTRY_AB3); show(&f, langinfo::_NL_ADDRESS_COUNTRY_CAR); show(&f, langinfo::_NL_ADDRESS_COUNTRY_ISBN); show(&f, langinfo::_NL_ADDRESS_LANG_NAME); show(&f, langinfo::_NL_ADDRESS_LANG_AB); show(&f, langinfo::_NL_ADDRESS_LANG_TERM); show(&f, langinfo::_NL_ADDRESS_LANG_LIB); show(&f, langinfo::_NL_TELEPHONE_TEL_INT_FMT); show(&f, langinfo::_NL_TELEPHONE_TEL_DOM_FMT); show(&f, langinfo::_NL_TELEPHONE_INT_SELECT); show(&f, langinfo::_NL_TELEPHONE_INT_PREFIX); show(&f, langinfo::__INT_FRAC_DIGITS); show(&f, langinfo::__FRAC_DIGITS); show(&f, langinfo::__P_CS_PRECEDES); show(&f, langinfo::__P_SEP_BY_SPACE); show(&f, langinfo::__N_CS_PRECEDES); show(&f, langinfo::__N_SEP_BY_SPACE); show(&f, langinfo::__P_SIGN_POSN); show(&f, langinfo::__N_SIGN_POSN); show(&f, langinfo::__INT_P_CS_PRECEDES); show(&f, langinfo::__INT_P_SEP_BY_SPACE); show(&f, langinfo::__INT_N_CS_PRECEDES); show(&f, langinfo::__INT_N_SEP_BY_SPACE); show(&f, langinfo::__INT_P_SIGN_POSN); show(&f, langinfo::__INT_N_SIGN_POSN); show(&f, langinfo::_NL_MONETARY_DUO_INT_FRAC_DIGITS); show(&f, langinfo::_NL_MONETARY_DUO_FRAC_DIGITS); show(&f, langinfo::_NL_MONETARY_DUO_P_CS_PRECEDES); show(&f, langinfo::_NL_MONETARY_DUO_P_SEP_BY_SPACE); show(&f, langinfo::_NL_MONETARY_DUO_N_CS_PRECEDES); show(&f, langinfo::_NL_MONETARY_DUO_N_SEP_BY_SPACE); show(&f, langinfo::_NL_MONETARY_DUO_INT_P_CS_PRECEDES); show(&f, langinfo::_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE); show(&f, langinfo::_NL_MONETARY_DUO_INT_N_CS_PRECEDES); show(&f, langinfo::_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE); show(&f, langinfo::_NL_MONETARY_DUO_P_SIGN_POSN); show(&f, langinfo::_NL_MONETARY_DUO_N_SIGN_POSN); show(&f, langinfo::_NL_MONETARY_DUO_INT_P_SIGN_POSN); show(&f, langinfo::_NL_MONETARY_DUO_INT_N_SIGN_POSN); show(&f, langinfo::_NL_TIME_WEEK_NDAYS); show(&f, langinfo::_NL_TIME_WEEK_1STWEEK); show(&f, langinfo::_NL_TIME_FIRST_WEEKDAY); show(&f, langinfo::_NL_TIME_FIRST_WORKDAY); show(&f, langinfo::_NL_TIME_CAL_DIRECTION); show(&f, langinfo::_NL_MEASUREMENT_MEASUREMENT); show(&f, langinfo::_NL_CTYPE_WIDTH); show(&f, langinfo::__MON_GROUPING); show(&f, langinfo::__GROUPING); show(&f, langinfo::_NL_COLLATE_NRULES); show(&f, langinfo::_NL_COLLATE_SYMB_HASH_SIZEMB); show(&f, langinfo::_NL_CTYPE_MB_CUR_MAX); show(&f, langinfo::_NL_CTYPE_CLASS_OFFSET); show(&f, langinfo::_NL_CTYPE_MAP_OFFSET); show(&f, langinfo::_NL_CTYPE_INDIGITS_MB_LEN); show(&f, langinfo::_NL_CTYPE_INDIGITS_WC_LEN); show(&f, langinfo::_NL_CTYPE_TRANSLIT_TAB_SIZE); show(&f, langinfo::_NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN); show(&f, langinfo::_NL_CTYPE_TRANSLIT_IGNORE_LEN); show(&f, langinfo::_NL_CTYPE_MAP_TO_NONASCII); show(&f, langinfo::_NL_CTYPE_NONASCII_CASE); show(&f, langinfo::_NL_MONETARY_UNO_VALID_FROM); show(&f, langinfo::_NL_MONETARY_UNO_VALID_TO); show(&f, langinfo::_NL_MONETARY_DUO_VALID_FROM); show(&f, langinfo::_NL_MONETARY_DUO_VALID_TO); show(&f, langinfo::_NL_TIME_ERA_NUM_ENTRIES); show(&f, langinfo::_NL_TIME_WEEK_1STDAY); show(&f, langinfo::_NL_PAPER_HEIGHT); show(&f, langinfo::_NL_PAPER_WIDTH); show(&f, langinfo::_NL_ADDRESS_COUNTRY_NUM); show(&f, langinfo::_NL_CTYPE_OUTDIGIT0_WC); show(&f, langinfo::_NL_CTYPE_OUTDIGIT1_WC); show(&f, langinfo::_NL_CTYPE_OUTDIGIT2_WC); show(&f, langinfo::_NL_CTYPE_OUTDIGIT3_WC); show(&f, langinfo::_NL_CTYPE_OUTDIGIT4_WC); show(&f, langinfo::_NL_CTYPE_OUTDIGIT5_WC); show(&f, langinfo::_NL_CTYPE_OUTDIGIT6_WC); show(&f, langinfo::_NL_CTYPE_OUTDIGIT7_WC); show(&f, langinfo::_NL_CTYPE_OUTDIGIT8_WC); show(&f, langinfo::_NL_CTYPE_OUTDIGIT9_WC); show(&f, langinfo::_NL_MONETARY_DECIMAL_POINT_WC); show(&f, langinfo::_NL_MONETARY_THOUSANDS_SEP_WC); show(&f, langinfo::_NL_NUMERIC_DECIMAL_POINT_WC); show(&f, langinfo::_NL_NUMERIC_THOUSANDS_SEP_WC); show(&f, langinfo::_NL_IDENTIFICATION_TITLE); show(&f, langinfo::_NL_IDENTIFICATION_SOURCE); show(&f, langinfo::_NL_IDENTIFICATION_ADDRESS); show(&f, langinfo::_NL_IDENTIFICATION_CONTACT); show(&f, langinfo::_NL_IDENTIFICATION_EMAIL); show(&f, langinfo::_NL_IDENTIFICATION_TEL); show(&f, langinfo::_NL_IDENTIFICATION_FAX); show(&f, langinfo::_NL_IDENTIFICATION_LANGUAGE); show(&f, langinfo::_NL_IDENTIFICATION_TERRITORY); show(&f, langinfo::_NL_IDENTIFICATION_AUDIENCE); show(&f, langinfo::_NL_IDENTIFICATION_APPLICATION); show(&f, langinfo::_NL_IDENTIFICATION_ABBREVIATION); show(&f, langinfo::_NL_IDENTIFICATION_REVISION); show(&f, langinfo::_NL_IDENTIFICATION_DATE); show(&f, langinfo::_NL_IDENTIFICATION_CATEGORY); } #[cfg(not(target_os = "linux"))] pub fn main() { println!("Listing locale info not (yet) supported on this system"); } locale-0.2.2/src/lib.rs01006440001750000175000000023227131121056570013105 0ustar0000000000000000#![crate_name = "locale"] #![crate_type = "rlib"] #![crate_type = "dylib"] //! Localisation is hard. //! //! Getting your program to work well in multiple languages is a world fraught with edge-cases, //! minor grammatical errors, and most importantly, subtle things that don't map over well that you //! have absolutely no idea are different in other cultures. //! //! Many people are aware of the simpler ones, such as whether to use decimal points or decimal //! commas, or that the names of the months are different in other languages. But there are also //! different ways to format dates and times, or variations on what day the week begins. It's //! perfectly possible to write your program unaware of how these things have to be changed at all, //! and that's why it's so hard. extern crate libc; use std::fmt::Display; use std::io::Result; /// Trait defining how to obtain various components of a locale. /// /// Use implementation of this trait to construct parts of the `Locale` object. /// /// There may be various methods for obtaining locale data. The lowest common denominator is /// standard C library. It is however quite limited and some systems (notably Android) don't /// actually contain the corresponding data. Many systems also provide additional configurability /// for the locale setting (Windows, KDE, etc.) that are only accessible via that system's specific /// interface. So this trait exists to allow combining the methods for obtaining the data. /// /// The implementations for individual locale categories are returned boxed, because they may need /// to be polymorphic _and_ in options to allow combining partial implementations. Creating locale /// data is not a performance critical operation, so dynamic polymrphism is used for sake of /// simplicity. /// /// All methods default to simply returning None, again so partial implementations that delegate to /// another factory are possible. See `CompositeLocaleFactory`. pub trait LocaleFactory { /// Get implementation of the Numeric locale category. fn get_numeric(&mut self) -> Option> { None } /// Get implementation of the Time locale category. fn get_time(&mut self) -> Option> { None } } /// Auxiliary class for creating composing partial implementations of locale factories. // FIXME: Create (doc) test when there actually is another implementation to substitute. #[derive(Debug, Clone)] pub struct CompositeLocaleFactory { first: First, second: Second, } impl CompositeLocaleFactory { pub fn new(first: F, second: S) -> Self { CompositeLocaleFactory:: { first: first, second: second } } } impl LocaleFactory for CompositeLocaleFactory { // XXX: Make a macro for this fn get_numeric(&mut self) -> Option> { if let Some(v) = self.first.get_numeric() { Some(v) } else { self.second.get_numeric() } } fn get_time(&mut self) -> Option> { if let Some(v) = self.first.get_time() { Some(v) } else { self.second.get_time() } } } /// Factory of invariant locales. /// /// Invariant locale, called "C" or "POSIX" by standard C library locale functions, is default /// locale definitions for when no information about desired locale is available or localization is /// turned off. #[derive(Debug, Clone, Default)] pub struct InvariantLocaleFactory; impl InvariantLocaleFactory { /// Constructs invariant locale factory. /// /// The signature is just so that it matches the other locale factories so the classes can be /// substituted depending on target operating system and the code using them does not have to /// care. #[allow(unused_variables)] pub fn new(locale: &str) -> Result { Ok(InvariantLocaleFactory) } } impl LocaleFactory for InvariantLocaleFactory { // NOTE: Yep, it's empty. This just returns nothing and the Locale constructor will take care // of the actual defaults. } #[cfg(target_os = "linux")] pub mod linux; #[cfg(target_os = "linux")] pub use linux::LibCLocaleFactory as SystemLocaleFactory; // FIXME: #[cfg(target_os = "macos")], but for the moment I need to test whether it compiles, don't // have MacOS box nor cross-compiler and it does not actually contain anything system-specific yet pub mod macos; #[cfg(target_os = "macos")] pub use macos::MacOSLocaleFactory as SystemLocaleFactory; #[cfg(not(any(target_os = "linux", target_os = "macos")))] pub use InvariantLocaleFactory as SystemLocaleFactory; /// Return LocaleFactory appropriate for default user locale, as far as it can be determined. /// /// The returned locale factory provides locale facets implemented using standard localization /// functionality of the underlying operating system and configured for user's default locale. // // FIXME: The global instance should simply default-initialize to default user locale with proper // fallback if it fails to construct and then we don't need this. pub fn user_locale_factory() -> SystemLocaleFactory { // FIXME: Error handling? Constructing locale with "" should never fail as far as I can tell. SystemLocaleFactory::new("").unwrap() } // ---- locale facets ---- // ---- numeric stuff ---- /// Information on how to format numbers. #[derive(Debug, Clone)] pub struct Numeric { /// The punctuation that separates the decimal part of a non-integer number. Usually a decimal /// point or a decimal comma. pub decimal_sep: String, /// The punctuation that separates groups of digits in long numbers. pub thousands_sep: String, } impl Numeric { pub fn load_user_locale() -> Result { if let Ok(mut factory) = SystemLocaleFactory::new("") { if let Some(numeric) = factory.get_numeric() { return Ok(*numeric); } } Ok(Numeric::english()) } pub fn english() -> Numeric { Numeric::new(".", ",") } pub fn new(decimal_sep: &str, thousands_sep: &str) -> Numeric { Numeric { decimal_sep: decimal_sep.to_string(), thousands_sep: thousands_sep.to_string(), } } pub fn format_int(&self, input: I) -> String { let s = input.to_string(); let mut buf = String::new(); for (i, c) in s.chars().enumerate() { buf.push(c); if (s.len() - i - 1) % 3 == 0 && i != s.len() - 1 { buf.push_str(&self.thousands_sep[..]); } } buf } pub fn format_float(&self, input: F, decimal_places: usize) -> String { format!("{:.*}", decimal_places, input).replace(".", &self.decimal_sep) } } // ---- time stuff --- #[derive(Debug, Clone)] pub struct Time { month_names: Vec, long_month_names: Vec, day_names: Vec, long_day_names: Vec, } impl Time { pub fn load_user_locale() -> Result