pseudolocalization 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.2
5
+ before_install: gem install bundler -v 1.16.0
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ ruby '~> 2.4'
2
+
3
+ source "https://rubygems.org"
4
+
5
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in pseudolocalization.gemspec
8
+ gemspec
@@ -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.
@@ -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.
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -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__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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,14 @@
1
+ name: pseudolocalization
2
+
3
+ type: ruby
4
+
5
+ up:
6
+ - ruby: 2.4.2
7
+ - bundler
8
+
9
+ commands:
10
+ test:
11
+ syntax:
12
+ argument: file
13
+ optional: args...
14
+ run: rake test
@@ -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,3 @@
1
+ module Pseudolocalization
2
+ VERSION = "0.4.0"
3
+ 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
@@ -0,0 +1,4 @@
1
+ deploy:
2
+ override:
3
+ - bundle exec rake build
4
+ - bundle exec package_cloud push shopify/gems pkg/*.gem
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: []