{"action":"closed","number":1,"pull_request":{"url":"https://api.github.com/repos/ogham/rust-locale/pulls/1","id":30931885,"html_url":"https://github.com/ogham/rust-locale/pull/1","diff_url":"https://github.com/ogham/rust-locale/pull/1.diff","patch_url":"https://github.com/ogham/rust-locale/pull/1.patch","issue_url":"https://api.github.com/repos/ogham/rust-locale/issues/1","number":1,"state":"closed","locked":false,"title":"Obtaining locale data from system (for Linux for now)","user":{"login":"jan-hudec","id":2624197,"avatar_url":"https://avatars.githubusercontent.com/u/2624197?v=3","gravatar_id":"","url":"https://api.github.com/users/jan-hudec","html_url":"https://github.com/jan-hudec","followers_url":"https://api.github.com/users/jan-hudec/followers","following_url":"https://api.github.com/users/jan-hudec/following{/other_user}","gists_url":"https://api.github.com/users/jan-hudec/gists{/gist_id}","starred_url":"https://api.github.com/users/jan-hudec/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jan-hudec/subscriptions","organizations_url":"https://api.github.com/users/jan-hudec/orgs","repos_url":"https://api.github.com/users/jan-hudec/repos","events_url":"https://api.github.com/users/jan-hudec/events{/privacy}","received_events_url":"https://api.github.com/users/jan-hudec/received_events","type":"User","site_admin":false},"body":"I've been thinking about writing localization module for Rust and since you've taken the most obvious crate name `locale` I would like to join you.\r\n\r\nI've done localization for work project in C++ where I needed to do most things myself, because no existing code was supported across all targets. So in the end I implemented formatting support (for things we needed; we don't need dates and monetary, but we have custom rounding and support for units), reader for libintl's `.mo` files and script to extract the needed bits of locale information from [CLDR] and storing them in the `.mo` files.\r\n\r\nAnd I would like to contribute something similar to Rust. This is the first batch of changes so we can discuss the approach. The overall plan is outlined below.\r\n\r\n# Plan\r\n\r\nThe plan is to create:\r\n\r\n 1. A locale-aware formatter that will work similarly to the `std::fmt` module, but will carry around additional object of type `locale::Locale` that will describe the locale-specific bits of formatting functionality.\r\n 2. A `locale::Locale` container that will hold individual locale facets in boxes with trait types. It will have explicit storage for the standard facets (`Numeric`, `Monetary`, `Time`, `Messages` etc.) and an option to attach custom data so users can pass additional information to formatting functions for their own types.\r\n 3. A well known instance (obtained as `Arc<Locale>`, so it can be set in a thread-safe way) that would be used for formatting by default. Setting it would not affect already existing formatters/streams (to be thread-safe).\r\n 4. Traits for the standard facets. I will in due time change the current `Numeric` and `Time` to traits and the current structs will become default implementations.\r\n 5. Standard implementations of those facets.\r\n    a. Some facets can be universal; e.g. `Numeric`, `Time` or `Monetary` can simply hold all the necessary attributes and provide formatting function to use them. I will extend them to hold and use all attributes defined by [CLDR].\r\n    b. Some facets will be system specific. For example `Collate` has to use `strcoll_l` and `strxfrm_l` on Linux, but [`CompareString`](https://msdn.microsoft.com/en-us/library/windows/desktop/dd317759(v=vs.85).aspx) and [`LCMapString`](https://msdn.microsoft.com/en-us/library/windows/desktop/dd318700(v=vs.85).aspx) on Windows.\r\n    c. Some facets may have alternate implementations. I will implement `Messages` facet using libintl `.mo` files, but other implementations are possible. I can imagine including [`catgets`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/catgets.html) or windows resources support in some later version.\r\n 6. Factory classes, implementing the `locale::LocaleFactory` trait, for getting the relevant data out of operating system and constructing the traits. This PR already implements this (to the extent facets are defined) for Linux and I plan to implement it for Windows (using the native API, because the libc API is very limited there) and implement extensions for KDE and GNOME (KDE has settings where parts of the locale information can be overridden). However I know nothing about MacOS X and don't have access to it, so I can't do that bit.\r\n\r\n    The idea of using factories is to encapsulate the system specific code, avoid duplication (once we get the `locale_t`, we can construct all facets from it) and to allow creating combined methods for obtaining the data (e.g. the KDE factory that reads some data from the KDE config file and delegates the rest to the libc implementation). It can be hidden from the user behind default constructor in `locale::Locale`.\r\n 6. Possibly implement facets using data extracted from CLDR and bundled with the application that could be used on systems where the native data is not available like Android.\r\n\r\n# This pull request\r\n\r\nSo far I've implemented the necessary binding to GNU LibC functions (creating `locale_t`, `nl_langinfo_l` for getting the data and `iconv` for converting them to utf-8 in case the user's locale has different codeset) and the factory traits. That you will find in this pull request.\r\n\r\nFor the time being I've left the functions `Numeric::load_user_locale` and `Time::load_user_locale` in, but they won't work on my system. I don't have the files they are trying to read (and I've generated all locales provided by the `locales` package) and don't have any files in the format they expect. For which system did you write those functions? The code from them should then end up in appropriate factory specific to that system.\r\n\r\n[CLDR]: http://cldr.unicode.org/","created_at":"2015-03-11T10:47:51Z","updated_at":"2015-03-13T22:48:19Z","closed_at":"2015-03-13T22:48:19Z","merged_at":"2015-03-13T22:48:19Z","merge_commit_sha":"c4a69a4c5ffd8e1ca5b5cbfa2582aaa877e40be5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ogham/rust-locale/pulls/1/commits","review_comments_url":"https://api.github.com/repos/ogham/rust-locale/pulls/1/comments","review_comment_url":"https://api.github.com/repos/ogham/rust-locale/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ogham/rust-locale/issues/1/comments","statuses_url":"https://api.github.com/repos/ogham/rust-locale/statuses/4af6bb82daba7ba98655792c80ea982171d7ee54","head":{"label":"jan-hudec:master","ref":"master","sha":"4af6bb82daba7ba98655792c80ea982171d7ee54","user":{"login":"jan-hudec","id":2624197,"avatar_url":"https://avatars.githubusercontent.com/u/2624197?v=3","gravatar_id":"","url":"https://api.github.com/users/jan-hudec","html_url":"https://github.com/jan-hudec","followers_url":"https://api.github.com/users/jan-hudec/followers","following_url":"https://api.github.com/users/jan-hudec/following{/other_user}","gists_url":"https://api.github.com/users/jan-hudec/gists{/gist_id}","starred_url":"https://api.github.com/users/jan-hudec/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jan-hudec/subscriptions","organizations_url":"https://api.github.com/users/jan-hudec/orgs","repos_url":"https://api.github.com/users/jan-hudec/repos","events_url":"https://api.github.com/users/jan-hudec/events{/privacy}","received_events_url":"https://api.github.com/users/jan-hudec/received_events","type":"User","site_admin":false},"repo":{"id":31473231,"name":"rust-locale","full_name":"jan-hudec/rust-locale","owner":{"login":"jan-hudec","id":2624197,"avatar_url":"https://avatars.githubusercontent.com/u/2624197?v=3","gravatar_id":"","url":"https://api.github.com/users/jan-hudec","html_url":"https://github.com/jan-hudec","followers_url":"https://api.github.com/users/jan-hudec/followers","following_url":"https://api.github.com/users/jan-hudec/following{/other_user}","gists_url":"https://api.github.com/users/jan-hudec/gists{/gist_id}","starred_url":"https://api.github.com/users/jan-hudec/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jan-hudec/subscriptions","organizations_url":"https://api.github.com/users/jan-hudec/orgs","repos_url":"https://api.github.com/users/jan-hudec/repos","events_url":"https://api.github.com/users/jan-hudec/events{/privacy}","received_events_url":"https://api.github.com/users/jan-hudec/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jan-hudec/rust-locale","description":"Library for getting the user's localisation settings","fork":true,"url":"https://api.github.com/repos/jan-hudec/rust-locale","forks_url":"https://api.github.com/repos/jan-hudec/rust-locale/forks","keys_url":"https://api.github.com/repos/jan-hudec/rust-locale/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jan-hudec/rust-locale/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jan-hudec/rust-locale/teams","hooks_url":"https://api.github.com/repos/jan-hudec/rust-locale/hooks","issue_events_url":"https://api.github.com/repos/jan-hudec/rust-locale/issues/events{/number}","events_url":"https://api.github.com/repos/jan-hudec/rust-locale/events","assignees_url":"https://api.github.com/repos/jan-hudec/rust-locale/assignees{/user}","branches_url":"https://api.github.com/repos/jan-hudec/rust-locale/branches{/branch}","tags_url":"https://api.github.com/repos/jan-hudec/rust-locale/tags","blobs_url":"https://api.github.com/repos/jan-hudec/rust-locale/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jan-hudec/rust-locale/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jan-hudec/rust-locale/git/refs{/sha}","trees_url":"https://api.github.com/repos/jan-hudec/rust-locale/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jan-hudec/rust-locale/statuses/{sha}","languages_url":"https://api.github.com/repos/jan-hudec/rust-locale/languages","stargazers_url":"https://api.github.com/repos/jan-hudec/rust-locale/stargazers","contributors_url":"https://api.github.com/repos/jan-hudec/rust-locale/contributors","subscribers_url":"https://api.github.com/repos/jan-hudec/rust-locale/subscribers","subscription_url":"https://api.github.com/repos/jan-hudec/rust-locale/subscription","commits_url":"https://api.github.com/repos/jan-hudec/rust-locale/commits{/sha}","git_commits_url":"https://api.github.com/repos/jan-hudec/rust-locale/git/commits{/sha}","comments_url":"https://api.github.com/repos/jan-hudec/rust-locale/comments{/number}","issue_comment_url":"https://api.github.com/repos/jan-hudec/rust-locale/issues/comments{/number}","contents_url":"https://api.github.com/repos/jan-hudec/rust-locale/contents/{+path}","compare_url":"https://api.github.com/repos/jan-hudec/rust-locale/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jan-hudec/rust-locale/merges","archive_url":"https://api.github.com/repos/jan-hudec/rust-locale/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jan-hudec/rust-locale/downloads","issues_url":"https://api.github.com/repos/jan-hudec/rust-locale/issues{/number}","pulls_url":"https://api.github.com/repos/jan-hudec/rust-locale/pulls{/number}","milestones_url":"https://api.github.com/repos/jan-hudec/rust-locale/milestones{/number}","notifications_url":"https://api.github.com/repos/jan-hudec/rust-locale/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jan-hudec/rust-locale/labels{/name}","releases_url":"https://api.github.com/repos/jan-hudec/rust-locale/releases{/id}","created_at":"2015-02-28T19:13:06Z","updated_at":"2015-03-11T19:28:13Z","pushed_at":"2015-03-11T19:28:12Z","git_url":"git://github.com/jan-hudec/rust-locale.git","ssh_url":"git@github.com:jan-hudec/rust-locale.git","clone_url":"https://github.com/jan-hudec/rust-locale.git","svn_url":"https://github.com/jan-hudec/rust-locale","homepage":null,"size":160,"stargazers_count":0,"watchers_count":0,"language":"Rust","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ogham:master","ref":"master","sha":"61be94975a44ea5abdafa893484dc2283d4d15c3","user":{"login":"ogham","id":503760,"avatar_url":"https://avatars.githubusercontent.com/u/503760?v=3","gravatar_id":"","url":"https://api.github.com/users/ogham","html_url":"https://github.com/ogham","followers_url":"https://api.github.com/users/ogham/followers","following_url":"https://api.github.com/users/ogham/following{/other_user}","gists_url":"https://api.github.com/users/ogham/gists{/gist_id}","starred_url":"https://api.github.com/users/ogham/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ogham/subscriptions","organizations_url":"https://api.github.com/users/ogham/orgs","repos_url":"https://api.github.com/users/ogham/repos","events_url":"https://api.github.com/users/ogham/events{/privacy}","received_events_url":"https://api.github.com/users/ogham/received_events","type":"User","site_admin":false},"repo":{"id":30599326,"name":"rust-locale","full_name":"ogham/rust-locale","owner":{"login":"ogham","id":503760,"avatar_url":"https://avatars.githubusercontent.com/u/503760?v=3","gravatar_id":"","url":"https://api.github.com/users/ogham","html_url":"https://github.com/ogham","followers_url":"https://api.github.com/users/ogham/followers","following_url":"https://api.github.com/users/ogham/following{/other_user}","gists_url":"https://api.github.com/users/ogham/gists{/gist_id}","starred_url":"https://api.github.com/users/ogham/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ogham/subscriptions","organizations_url":"https://api.github.com/users/ogham/orgs","repos_url":"https://api.github.com/users/ogham/repos","events_url":"https://api.github.com/users/ogham/events{/privacy}","received_events_url":"https://api.github.com/users/ogham/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ogham/rust-locale","description":"Library for getting the user's localisation settings","fork":false,"url":"https://api.github.com/repos/ogham/rust-locale","forks_url":"https://api.github.com/repos/ogham/rust-locale/forks","keys_url":"https://api.github.com/repos/ogham/rust-locale/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ogham/rust-locale/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ogham/rust-locale/teams","hooks_url":"https://api.github.com/repos/ogham/rust-locale/hooks","issue_events_url":"https://api.github.com/repos/ogham/rust-locale/issues/events{/number}","events_url":"https://api.github.com/repos/ogham/rust-locale/events","assignees_url":"https://api.github.com/repos/ogham/rust-locale/assignees{/user}","branches_url":"https://api.github.com/repos/ogham/rust-locale/branches{/branch}","tags_url":"https://api.github.com/repos/ogham/rust-locale/tags","blobs_url":"https://api.github.com/repos/ogham/rust-locale/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ogham/rust-locale/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ogham/rust-locale/git/refs{/sha}","trees_url":"https://api.github.com/repos/ogham/rust-locale/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ogham/rust-locale/statuses/{sha}","languages_url":"https://api.github.com/repos/ogham/rust-locale/languages","stargazers_url":"https://api.github.com/repos/ogham/rust-locale/stargazers","contributors_url":"https://api.github.com/repos/ogham/rust-locale/contributors","subscribers_url":"https://api.github.com/repos/ogham/rust-locale/subscribers","subscription_url":"https://api.github.com/repos/ogham/rust-locale/subscription","commits_url":"https://api.github.com/repos/ogham/rust-locale/commits{/sha}","git_commits_url":"https://api.github.com/repos/ogham/rust-locale/git/commits{/sha}","comments_url":"https://api.github.com/repos/ogham/rust-locale/comments{/number}","issue_comment_url":"https://api.github.com/repos/ogham/rust-locale/issues/comments{/number}","contents_url":"https://api.github.com/repos/ogham/rust-locale/contents/{+path}","compare_url":"https://api.github.com/repos/ogham/rust-locale/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ogham/rust-locale/merges","archive_url":"https://api.github.com/repos/ogham/rust-locale/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ogham/rust-locale/downloads","issues_url":"https://api.github.com/repos/ogham/rust-locale/issues{/number}","pulls_url":"https://api.github.com/repos/ogham/rust-locale/pulls{/number}","milestones_url":"https://api.github.com/repos/ogham/rust-locale/milestones{/number}","notifications_url":"https://api.github.com/repos/ogham/rust-locale/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ogham/rust-locale/labels{/name}","releases_url":"https://api.github.com/repos/ogham/rust-locale/releases{/id}","created_at":"2015-02-10T15:42:52Z","updated_at":"2015-03-13T22:48:20Z","pushed_at":"2015-03-13T22:48:20Z","git_url":"git://github.com/ogham/rust-locale.git","ssh_url":"git@github.com:ogham/rust-locale.git","clone_url":"https://github.com/ogham/rust-locale.git","svn_url":"https://github.com/ogham/rust-locale","homepage":null,"size":165,"stargazers_count":0,"watchers_count":0,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ogham/rust-locale/pulls/1"},"html":{"href":"https://github.com/ogham/rust-locale/pull/1"},"issue":{"href":"https://api.github.com/repos/ogham/rust-locale/issues/1"},"comments":{"href":"https://api.github.com/repos/ogham/rust-locale/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/ogham/rust-locale/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/ogham/rust-locale/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ogham/rust-locale/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/ogham/rust-locale/statuses/4af6bb82daba7ba98655792c80ea982171d7ee54"}},"merged":true,"mergeable":null,"mergeable_state":"unknown","merged_by":{"login":"ogham","id":503760,"avatar_url":"https://avatars.githubusercontent.com/u/503760?v=3","gravatar_id":"","url":"https://api.github.com/users/ogham","html_url":"https://github.com/ogham","followers_url":"https://api.github.com/users/ogham/followers","following_url":"https://api.github.com/users/ogham/following{/other_user}","gists_url":"https://api.github.com/users/ogham/gists{/gist_id}","starred_url":"https://api.github.com/users/ogham/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ogham/subscriptions","organizations_url":"https://api.github.com/users/ogham/orgs","repos_url":"https://api.github.com/users/ogham/repos","events_url":"https://api.github.com/users/ogham/events{/privacy}","received_events_url":"https://api.github.com/users/ogham/received_events","type":"User","site_admin":false},"comments":4,"review_comments":3,"commits":7,"additions":920,"deletions":4,"changed_files":5}}