pseudolocalization 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +5 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +51 -0
- data/LICENSE +20 -0
- data/README.md +69 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/circle.yml +15 -0
- data/dev.yml +14 -0
- data/lib/pseudolocalization.rb +121 -0
- data/lib/pseudolocalization/version.rb +3 -0
- data/pseudolocalization.gemspec +26 -0
- data/shipit.yml +4 -0
- metadata +87 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5e5dc2b093b49d1731d6ddbfc5d00453034db141
|
4
|
+
data.tar.gz: 335002ef3a837e7a1b8beb06eae102e223e4e973
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2fd4bcc39748f2a0082866f15f634c870e9074a5446774394795d7cbe3428caed911aeafdfa23059784943dac737e95ddf34e5373418b0981101fe42eb47c215
|
7
|
+
data.tar.gz: 9f9484056e22ba0ddc6176c61c74288827a9cadc5320be34ad68185cae81e7b5ec44afeccb3f9a9d1d7b468005b293b48049288bf9274d5c6091ac6aa039bc06
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pseudolocalization (0.2.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
domain_name (0.5.20170404)
|
10
|
+
unf (>= 0.0.5, < 1.0.0)
|
11
|
+
highline (1.6.20)
|
12
|
+
http-cookie (1.0.3)
|
13
|
+
domain_name (~> 0.5)
|
14
|
+
json_pure (1.8.1)
|
15
|
+
mime-types (3.1)
|
16
|
+
mime-types-data (~> 3.2015)
|
17
|
+
mime-types-data (3.2016.0521)
|
18
|
+
minitest (5.11.3)
|
19
|
+
netrc (0.11.0)
|
20
|
+
package_cloud (0.3.04)
|
21
|
+
highline (= 1.6.20)
|
22
|
+
json_pure (= 1.8.1)
|
23
|
+
rainbow (= 2.2.2)
|
24
|
+
rest-client (~> 2.0)
|
25
|
+
thor (~> 0.18)
|
26
|
+
rainbow (2.2.2)
|
27
|
+
rake
|
28
|
+
rake (10.5.0)
|
29
|
+
rest-client (2.0.2)
|
30
|
+
http-cookie (>= 1.0.2, < 2.0)
|
31
|
+
mime-types (>= 1.16, < 4.0)
|
32
|
+
netrc (~> 0.8)
|
33
|
+
thor (0.20.0)
|
34
|
+
unf (0.1.4)
|
35
|
+
unf_ext
|
36
|
+
unf_ext (0.0.7.5)
|
37
|
+
|
38
|
+
PLATFORMS
|
39
|
+
ruby
|
40
|
+
|
41
|
+
DEPENDENCIES
|
42
|
+
minitest (~> 5.0)
|
43
|
+
package_cloud
|
44
|
+
pseudolocalization!
|
45
|
+
rake (~> 10.0)
|
46
|
+
|
47
|
+
RUBY VERSION
|
48
|
+
ruby 2.4.2p198
|
49
|
+
|
50
|
+
BUNDLED WITH
|
51
|
+
1.16.1
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012-2013 Shopify Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Pseudolocalization
|
2
|
+
|
3
|
+
> Pseudolocalization (or pseudo-localization) is a software testing method used for testing internationalization aspects of software. Instead of translating the text of the software into a foreign language, as in the process of localization, the textual elements of an application are replaced with an altered version of the original language.
|
4
|
+
|
5
|
+
## Why?
|
6
|
+
|
7
|
+
Internationalization is a hard and tedious process. Different character sets, different average word length, different pluralization rules... There's a lot going on and it's impossible to test against all possible scenarios. As a side effect, most of us will simply test against one or two known languages and hope for the best. Unfortunately, this often leads to broken UI elements, texts going out of bounds, or forgotten non-translated strings making their way into a final release.
|
8
|
+
|
9
|
+
As an example, let's examine the string "Set the power switch to 0.";
|
10
|
+
|
11
|
+
| Language | String | Characters | Percentage |
|
12
|
+
|----------|--------|------------|------------|
|
13
|
+
| English | Set the power switch to 0. | 26 chars | -
|
14
|
+
| French | Placez l'interrupteur de tension à 0. | 37 chars | 42% more
|
15
|
+
| Spanish | Ponga el interruptor de alimentación de corriente en 0. | 55 chars | 112% more
|
16
|
+
|
17
|
+
It's easy to see that any hardcoded widths would likely break giving such a string. IBM suggests that on average, we should expect any English string to inflate by 30% when translating in another language.
|
18
|
+
|
19
|
+
In an attempt to ease this whole process, we created a small tool that gives you the ability to preview your product with pseudo-translations in a way that will;
|
20
|
+
|
21
|
+
1. Identify untranslated strings
|
22
|
+
2. Expand words by doubling all vowels
|
23
|
+
3. Use English lookalike UTF8 characters for readability
|
24
|
+
|
25
|
+
## Installation
|
26
|
+
|
27
|
+
Add these lines to your application's Gemfile:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
group :development do
|
31
|
+
gem 'pseudolocalization', require: false
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
Execute:
|
36
|
+
|
37
|
+
$ bundle
|
38
|
+
|
39
|
+
Finally, in an initializer, add the following lines:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
if Rails.env.development? && ENV["I18N_BACKEND"]
|
43
|
+
case ENV["I18N_BACKEND"]
|
44
|
+
when 'pseudolocalization'
|
45
|
+
require 'pseudolocalization'
|
46
|
+
I18n.backend = Pseudolocalization::I18n::Backend.new(I18n.backend)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
## Usage
|
52
|
+
|
53
|
+
When working on internationalization, you can boot your server with the pseudolocalization backend to quickly identify content that doesn't go through the I18n framework.
|
54
|
+
|
55
|
+
```bash
|
56
|
+
I18N_BACKEND=pseudolocalization bundle exec rails server
|
57
|
+
```
|
58
|
+
|
59
|
+
|
60
|
+
## Other Resources
|
61
|
+
|
62
|
+
* [IBM Globalization Guidelines](http://www-01.ibm.com/software/globalization/guidelines/index.html)
|
63
|
+
* [Design for internationalization - Dropbox Design](https://medium.com/dropbox-design/design-for-internationalization-24c12ea6b38f)
|
64
|
+
* [Pseudolocalization](https://en.wikipedia.org/wiki/Pseudolocalization)
|
65
|
+
* [Essential Guide to App Internationalization](https://drive.google.com/open?id=1c6nAw6ttF_uHRq0ZQaGu5gYD0vjq9lHP)
|
66
|
+
|
67
|
+
## Contributing
|
68
|
+
|
69
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Shopify/pseudolocalization.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "pseudolocalization"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/circle.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
machine:
|
2
|
+
environment:
|
3
|
+
RAILS_ENV: test
|
4
|
+
RACK_ENV: test
|
5
|
+
ruby:
|
6
|
+
version:
|
7
|
+
2.4.2
|
8
|
+
|
9
|
+
dependencies:
|
10
|
+
override:
|
11
|
+
- bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
|
12
|
+
|
13
|
+
database:
|
14
|
+
override:
|
15
|
+
- echo "no database setup"
|
data/dev.yml
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
require "pseudolocalization/version"
|
2
|
+
|
3
|
+
module Pseudolocalization
|
4
|
+
module I18n
|
5
|
+
class Backend
|
6
|
+
BRACKET_START = '<'
|
7
|
+
BRACKET_END = '>'
|
8
|
+
|
9
|
+
VOWELS = %w(a e i o u y A E I O U Y)
|
10
|
+
|
11
|
+
LETTERS = {
|
12
|
+
'a' => 'α',
|
13
|
+
'b' => 'ḅ',
|
14
|
+
'c' => 'ͼ',
|
15
|
+
'd' => 'ḍ',
|
16
|
+
'e' => 'ḛ',
|
17
|
+
'f' => 'ϝ',
|
18
|
+
'g' => 'ḡ',
|
19
|
+
'h' => 'ḥ',
|
20
|
+
'i' => 'ḭ',
|
21
|
+
'j' => 'ĵ',
|
22
|
+
'k' => 'ḳ',
|
23
|
+
'l' => 'ḽ',
|
24
|
+
'm' => 'ṃ',
|
25
|
+
'n' => 'ṇ',
|
26
|
+
'o' => 'ṓ',
|
27
|
+
'p' => 'ṗ',
|
28
|
+
'q' => 'ʠ',
|
29
|
+
'r' => 'ṛ',
|
30
|
+
's' => 'ṡ',
|
31
|
+
't' => 'ṭ',
|
32
|
+
'u' => 'ṵ',
|
33
|
+
'v' => 'ṽ',
|
34
|
+
'w' => 'ẁ',
|
35
|
+
'x' => 'ẋ',
|
36
|
+
'y' => 'ẏ',
|
37
|
+
'z' => 'ẓ',
|
38
|
+
'A' => 'Ḁ',
|
39
|
+
'B' => 'Ḃ',
|
40
|
+
'C' => 'Ḉ',
|
41
|
+
'D' => 'Ḍ',
|
42
|
+
'E' => 'Ḛ',
|
43
|
+
'F' => 'Ḟ',
|
44
|
+
'G' => 'Ḡ',
|
45
|
+
'H' => 'Ḥ',
|
46
|
+
'I' => 'Ḭ',
|
47
|
+
'J' => 'Ĵ',
|
48
|
+
'K' => 'Ḱ',
|
49
|
+
'L' => 'Ḻ',
|
50
|
+
'M' => 'Ṁ',
|
51
|
+
'N' => 'Ṅ',
|
52
|
+
'O' => 'Ṏ',
|
53
|
+
'P' => 'Ṕ',
|
54
|
+
'Q' => 'Ǫ',
|
55
|
+
'R' => 'Ṛ',
|
56
|
+
'S' => 'Ṣ',
|
57
|
+
'T' => 'Ṫ',
|
58
|
+
'U' => 'Ṳ',
|
59
|
+
'V' => 'Ṿ',
|
60
|
+
'W' => 'Ŵ',
|
61
|
+
'X' => 'Ẋ',
|
62
|
+
'Y' => 'Ŷ',
|
63
|
+
'Z' => 'Ż',
|
64
|
+
}.freeze
|
65
|
+
|
66
|
+
def initialize(old_backend)
|
67
|
+
@old_backend = old_backend
|
68
|
+
end
|
69
|
+
|
70
|
+
def method_missing(name, *args, &block)
|
71
|
+
if respond_to_missing?(name)
|
72
|
+
@old_backend.public_send(name, *args, &block)
|
73
|
+
else
|
74
|
+
super
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def respond_to_missing?(name, include_private = false)
|
79
|
+
@old_backend.respond_to?(name) || super
|
80
|
+
end
|
81
|
+
|
82
|
+
def translate(locale, key, options)
|
83
|
+
translate_object(@old_backend.translate(locale, key, options))
|
84
|
+
end
|
85
|
+
|
86
|
+
def translate_object(object)
|
87
|
+
if object.is_a?(Hash)
|
88
|
+
object.transform_values { |value| translate_object(value) }
|
89
|
+
elsif object.is_a?(Array)
|
90
|
+
object.map { |value| translate_object(value) }
|
91
|
+
elsif object.is_a?(String)
|
92
|
+
translate_string(object)
|
93
|
+
else
|
94
|
+
object
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def translate_string(string)
|
99
|
+
string = string.gsub(/&[a-z]+;/, ' ')
|
100
|
+
|
101
|
+
outside_brackets = true
|
102
|
+
|
103
|
+
string.chars.map do |char|
|
104
|
+
if char == BRACKET_START
|
105
|
+
outside_brackets = false
|
106
|
+
char
|
107
|
+
elsif char == BRACKET_END
|
108
|
+
outside_brackets = true
|
109
|
+
char
|
110
|
+
elsif outside_brackets && LETTERS.key?(char)
|
111
|
+
ret = LETTERS[char]
|
112
|
+
ret = ret * 2 if VOWELS.include?(char)
|
113
|
+
ret
|
114
|
+
else
|
115
|
+
char
|
116
|
+
end
|
117
|
+
end.join
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "pseudolocalization/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "pseudolocalization"
|
8
|
+
spec.version = Pseudolocalization::VERSION
|
9
|
+
spec.authors = ["Christian Blais"]
|
10
|
+
spec.email = ["christ.blais@gmail.com"]
|
11
|
+
spec.licenses = ['MIT']
|
12
|
+
|
13
|
+
spec.summary = %q{Internationalization development tool}
|
14
|
+
spec.description = %q{Internationalization development tool to help identify missing translations}
|
15
|
+
spec.homepage = "https://github.com/Shopify/pseudolocalization"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
26
|
+
end
|
data/shipit.yml
ADDED
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pseudolocalization
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Christian Blais
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-02-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '10.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '10.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.0'
|
41
|
+
description: Internationalization development tool to help identify missing translations
|
42
|
+
email:
|
43
|
+
- christ.blais@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- ".travis.yml"
|
50
|
+
- Gemfile
|
51
|
+
- Gemfile.lock
|
52
|
+
- LICENSE
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- bin/console
|
56
|
+
- bin/setup
|
57
|
+
- circle.yml
|
58
|
+
- dev.yml
|
59
|
+
- lib/pseudolocalization.rb
|
60
|
+
- lib/pseudolocalization/version.rb
|
61
|
+
- pseudolocalization.gemspec
|
62
|
+
- shipit.yml
|
63
|
+
homepage: https://github.com/Shopify/pseudolocalization
|
64
|
+
licenses:
|
65
|
+
- MIT
|
66
|
+
metadata: {}
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 2.6.14
|
84
|
+
signing_key:
|
85
|
+
specification_version: 4
|
86
|
+
summary: Internationalization development tool
|
87
|
+
test_files: []
|