pseudolocalization 0.5.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.dependabot/config.yml +18 -0
- data/.travis.yml +12 -3
- data/Gemfile +4 -2
- data/Gemfile.lock +13 -11
- data/README.md +5 -1
- data/dev.yml +1 -1
- data/lib/pseudolocalization.rb +8 -105
- data/lib/pseudolocalization/pseudolocalizer.rb +110 -0
- data/lib/pseudolocalization/version.rb +1 -1
- data/pseudolocalization.gemspec +1 -1
- data/service.yml +10 -0
- data/shipit.yml +3 -0
- metadata +8 -6
- data/circle.yml +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fa35c046d40aed5ede174170f02a87434358c60b
|
4
|
+
data.tar.gz: c1fd6b3caac2aa1eee62e1593c9be71a9cbe71b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25c6856e16c25134dc34548d6880f6374b36013603168d2577409fd3ba6be7b250817cc72992492b82ee6ecd994d708f0188f066141d1fecbc104b9d66e1e156
|
7
|
+
data.tar.gz: 2aeaf569ec791223a54f113d00207dc6f4616b29911622bb3d73f9e9b73a05902ec2b24e96f90ee79dbcd93b6f27ad10845d98329506756ed34901768c12bbba
|
@@ -0,0 +1,18 @@
|
|
1
|
+
version: 1
|
2
|
+
update_configs:
|
3
|
+
# Update your Gemfile (& lockfiles) as soon as
|
4
|
+
# new versions are published to the RubyGems registry
|
5
|
+
- package_manager: "ruby:bundler"
|
6
|
+
directory: "/"
|
7
|
+
update_schedule: "weekly"
|
8
|
+
|
9
|
+
# Apply default reviewer and label to created
|
10
|
+
# pull requests
|
11
|
+
default_reviewers:
|
12
|
+
- ChristianBlais
|
13
|
+
- larouxn
|
14
|
+
default_labels:
|
15
|
+
- "Gem upgrades"
|
16
|
+
|
17
|
+
version_requirement_updates: "auto"
|
18
|
+
|
data/.travis.yml
CHANGED
@@ -1,5 +1,14 @@
|
|
1
|
-
sudo: false
|
2
1
|
language: ruby
|
3
2
|
rvm:
|
4
|
-
- 2.4.
|
5
|
-
|
3
|
+
- 2.4.6
|
4
|
+
- 2.5.5
|
5
|
+
- 2.6.3
|
6
|
+
before_install:
|
7
|
+
- gem update --system
|
8
|
+
- gem install bundler -v '1.17.3'
|
9
|
+
cache:
|
10
|
+
bundler: true
|
11
|
+
install:
|
12
|
+
- bundle install
|
13
|
+
script:
|
14
|
+
- bundle exec rake test
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,23 +1,24 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pseudolocalization (0.
|
4
|
+
pseudolocalization (0.8.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
domain_name (0.5.
|
9
|
+
domain_name (0.5.20190701)
|
10
10
|
unf (>= 0.0.5, < 1.0.0)
|
11
11
|
highline (1.6.20)
|
12
|
+
http-accept (1.7.0)
|
12
13
|
http-cookie (1.0.3)
|
13
14
|
domain_name (~> 0.5)
|
14
15
|
json_pure (1.8.1)
|
15
|
-
mime-types (3.
|
16
|
+
mime-types (3.2.2)
|
16
17
|
mime-types-data (~> 3.2015)
|
17
|
-
mime-types-data (3.
|
18
|
+
mime-types-data (3.2019.0331)
|
18
19
|
minitest (5.11.3)
|
19
20
|
netrc (0.11.0)
|
20
|
-
package_cloud (0.3.
|
21
|
+
package_cloud (0.3.05)
|
21
22
|
highline (= 1.6.20)
|
22
23
|
json_pure (= 1.8.1)
|
23
24
|
rainbow (= 2.2.2)
|
@@ -25,15 +26,16 @@ GEM
|
|
25
26
|
thor (~> 0.18)
|
26
27
|
rainbow (2.2.2)
|
27
28
|
rake
|
28
|
-
rake (
|
29
|
-
rest-client (2.0
|
29
|
+
rake (12.3.3)
|
30
|
+
rest-client (2.1.0)
|
31
|
+
http-accept (>= 1.7.0, < 2.0)
|
30
32
|
http-cookie (>= 1.0.2, < 2.0)
|
31
33
|
mime-types (>= 1.16, < 4.0)
|
32
34
|
netrc (~> 0.8)
|
33
|
-
thor (0.20.
|
35
|
+
thor (0.20.3)
|
34
36
|
unf (0.1.4)
|
35
37
|
unf_ext
|
36
|
-
unf_ext (0.0.7.
|
38
|
+
unf_ext (0.0.7.6)
|
37
39
|
|
38
40
|
PLATFORMS
|
39
41
|
ruby
|
@@ -42,10 +44,10 @@ DEPENDENCIES
|
|
42
44
|
minitest (~> 5.0)
|
43
45
|
package_cloud
|
44
46
|
pseudolocalization!
|
45
|
-
rake (~>
|
47
|
+
rake (~> 12.3)
|
46
48
|
|
47
49
|
RUBY VERSION
|
48
50
|
ruby 2.4.2p198
|
49
51
|
|
50
52
|
BUNDLED WITH
|
51
|
-
1.
|
53
|
+
1.17.3
|
data/README.md
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
# Pseudolocalization
|
1
|
+
# Pseudolocalization [![Version][gem]][gem_url] [](https://travis-ci.org/Shopify/pseudolocalization)
|
2
|
+
|
3
|
+
[gem]: https://img.shields.io/gem/v/pseudolocalization.svg
|
4
|
+
[gem_url]: https://rubygems.org/gems/pseudolocalization
|
2
5
|
|
3
6
|
> 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
7
|
|
@@ -63,6 +66,7 @@ I18N_BACKEND=pseudolocalization bundle exec rails server
|
|
63
66
|
* [Design for internationalization - Dropbox Design](https://medium.com/dropbox-design/design-for-internationalization-24c12ea6b38f)
|
64
67
|
* [Pseudolocalization](https://en.wikipedia.org/wiki/Pseudolocalization)
|
65
68
|
* [Essential Guide to App Internationalization](https://drive.google.com/open?id=1c6nAw6ttF_uHRq0ZQaGu5gYD0vjq9lHP)
|
69
|
+
* [Pseudo Localization @ Netflix](https://medium.com/netflix-techblog/pseudo-localization-netflix-12fff76fbcbe)
|
66
70
|
|
67
71
|
## Contributing
|
68
72
|
|
data/dev.yml
CHANGED
data/lib/pseudolocalization.rb
CHANGED
@@ -1,126 +1,29 @@
|
|
1
|
-
|
1
|
+
require_relative "pseudolocalization/version"
|
2
|
+
require_relative "pseudolocalization/pseudolocalizer"
|
2
3
|
|
3
4
|
module Pseudolocalization
|
4
5
|
module I18n
|
5
6
|
class Backend
|
6
|
-
|
7
|
-
['<', '>'],
|
8
|
-
['{{', '}}'],
|
9
|
-
]
|
7
|
+
attr_reader :original_backend
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
ESCAPED_REGEX = Regexp.new("(#{ESCAPED_PATTERNS.join('|')})")
|
16
|
-
|
17
|
-
VOWELS = %w(a e i o u y A E I O U Y)
|
18
|
-
|
19
|
-
LETTERS = {
|
20
|
-
'a' => 'α',
|
21
|
-
'b' => 'ḅ',
|
22
|
-
'c' => 'ͼ',
|
23
|
-
'd' => 'ḍ',
|
24
|
-
'e' => 'ḛ',
|
25
|
-
'f' => 'ϝ',
|
26
|
-
'g' => 'ḡ',
|
27
|
-
'h' => 'ḥ',
|
28
|
-
'i' => 'ḭ',
|
29
|
-
'j' => 'ĵ',
|
30
|
-
'k' => 'ḳ',
|
31
|
-
'l' => 'ḽ',
|
32
|
-
'm' => 'ṃ',
|
33
|
-
'n' => 'ṇ',
|
34
|
-
'o' => 'ṓ',
|
35
|
-
'p' => 'ṗ',
|
36
|
-
'q' => 'ʠ',
|
37
|
-
'r' => 'ṛ',
|
38
|
-
's' => 'ṡ',
|
39
|
-
't' => 'ṭ',
|
40
|
-
'u' => 'ṵ',
|
41
|
-
'v' => 'ṽ',
|
42
|
-
'w' => 'ẁ',
|
43
|
-
'x' => 'ẋ',
|
44
|
-
'y' => 'ẏ',
|
45
|
-
'z' => 'ẓ',
|
46
|
-
'A' => 'Ḁ',
|
47
|
-
'B' => 'Ḃ',
|
48
|
-
'C' => 'Ḉ',
|
49
|
-
'D' => 'Ḍ',
|
50
|
-
'E' => 'Ḛ',
|
51
|
-
'F' => 'Ḟ',
|
52
|
-
'G' => 'Ḡ',
|
53
|
-
'H' => 'Ḥ',
|
54
|
-
'I' => 'Ḭ',
|
55
|
-
'J' => 'Ĵ',
|
56
|
-
'K' => 'Ḱ',
|
57
|
-
'L' => 'Ḻ',
|
58
|
-
'M' => 'Ṁ',
|
59
|
-
'N' => 'Ṅ',
|
60
|
-
'O' => 'Ṏ',
|
61
|
-
'P' => 'Ṕ',
|
62
|
-
'Q' => 'Ǫ',
|
63
|
-
'R' => 'Ṛ',
|
64
|
-
'S' => 'Ṣ',
|
65
|
-
'T' => 'Ṫ',
|
66
|
-
'U' => 'Ṳ',
|
67
|
-
'V' => 'Ṿ',
|
68
|
-
'W' => 'Ŵ',
|
69
|
-
'X' => 'Ẋ',
|
70
|
-
'Y' => 'Ŷ',
|
71
|
-
'Z' => 'Ż',
|
72
|
-
}.freeze
|
73
|
-
|
74
|
-
def initialize(old_backend)
|
75
|
-
@old_backend = old_backend
|
9
|
+
def initialize(original_backend)
|
10
|
+
@original_backend = original_backend
|
76
11
|
end
|
77
12
|
|
78
13
|
def method_missing(name, *args, &block)
|
79
14
|
if respond_to_missing?(name)
|
80
|
-
|
15
|
+
original_backend.public_send(name, *args, &block)
|
81
16
|
else
|
82
17
|
super
|
83
18
|
end
|
84
19
|
end
|
85
20
|
|
86
21
|
def respond_to_missing?(name, include_private = false)
|
87
|
-
|
22
|
+
original_backend.respond_to?(name) || super
|
88
23
|
end
|
89
24
|
|
90
25
|
def translate(locale, key, options)
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
def translate_object(object)
|
95
|
-
if object.is_a?(Hash)
|
96
|
-
object.transform_values { |value| translate_object(value) }
|
97
|
-
elsif object.is_a?(Array)
|
98
|
-
object.map { |value| translate_object(value) }
|
99
|
-
elsif object.is_a?(String)
|
100
|
-
translate_string(object)
|
101
|
-
else
|
102
|
-
object
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def translate_string(string)
|
107
|
-
string = string.gsub(/&[a-z]+;/, ' ')
|
108
|
-
|
109
|
-
string.split(ESCAPED_REGEX).map do |part|
|
110
|
-
if part =~ ESCAPED_REGEX
|
111
|
-
part
|
112
|
-
else
|
113
|
-
part.chars.map do |char|
|
114
|
-
if LETTERS.key?(char)
|
115
|
-
value = LETTERS[char]
|
116
|
-
value = value * 2 if VOWELS.include?(char)
|
117
|
-
value
|
118
|
-
else
|
119
|
-
char
|
120
|
-
end
|
121
|
-
end.join
|
122
|
-
end
|
123
|
-
end.join
|
26
|
+
::Pseudolocalization::I18n::Pseudolocalizer.pseudolocalize(original_backend.translate(locale, key, options))
|
124
27
|
end
|
125
28
|
end
|
126
29
|
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Pseudolocalization
|
2
|
+
module I18n
|
3
|
+
class Pseudolocalizer
|
4
|
+
ESCAPED_REGEX = Regexp.new("(#{
|
5
|
+
[
|
6
|
+
"<.*?>",
|
7
|
+
"{{.*?}}",
|
8
|
+
"https?:\/\/\\S+",
|
9
|
+
"&\\S*?;"
|
10
|
+
].join('|')
|
11
|
+
})")
|
12
|
+
|
13
|
+
VOWELS = %w(a e i o u y A E I O U Y)
|
14
|
+
|
15
|
+
LETTERS = {
|
16
|
+
'a' => 'α',
|
17
|
+
'b' => 'ḅ',
|
18
|
+
'c' => 'ͼ',
|
19
|
+
'd' => 'ḍ',
|
20
|
+
'e' => 'ḛ',
|
21
|
+
'f' => 'ϝ',
|
22
|
+
'g' => 'ḡ',
|
23
|
+
'h' => 'ḥ',
|
24
|
+
'i' => 'ḭ',
|
25
|
+
'j' => 'ĵ',
|
26
|
+
'k' => 'ḳ',
|
27
|
+
'l' => 'ḽ',
|
28
|
+
'm' => 'ṃ',
|
29
|
+
'n' => 'ṇ',
|
30
|
+
'o' => 'ṓ',
|
31
|
+
'p' => 'ṗ',
|
32
|
+
'q' => 'ʠ',
|
33
|
+
'r' => 'ṛ',
|
34
|
+
's' => 'ṡ',
|
35
|
+
't' => 'ṭ',
|
36
|
+
'u' => 'ṵ',
|
37
|
+
'v' => 'ṽ',
|
38
|
+
'w' => 'ẁ',
|
39
|
+
'x' => 'ẋ',
|
40
|
+
'y' => 'ẏ',
|
41
|
+
'z' => 'ẓ',
|
42
|
+
'A' => 'Ḁ',
|
43
|
+
'B' => 'Ḃ',
|
44
|
+
'C' => 'Ḉ',
|
45
|
+
'D' => 'Ḍ',
|
46
|
+
'E' => 'Ḛ',
|
47
|
+
'F' => 'Ḟ',
|
48
|
+
'G' => 'Ḡ',
|
49
|
+
'H' => 'Ḥ',
|
50
|
+
'I' => 'Ḭ',
|
51
|
+
'J' => 'Ĵ',
|
52
|
+
'K' => 'Ḱ',
|
53
|
+
'L' => 'Ḻ',
|
54
|
+
'M' => 'Ṁ',
|
55
|
+
'N' => 'Ṅ',
|
56
|
+
'O' => 'Ṏ',
|
57
|
+
'P' => 'Ṕ',
|
58
|
+
'Q' => 'Ǫ',
|
59
|
+
'R' => 'Ṛ',
|
60
|
+
'S' => 'Ṣ',
|
61
|
+
'T' => 'Ṫ',
|
62
|
+
'U' => 'Ṳ',
|
63
|
+
'V' => 'Ṿ',
|
64
|
+
'W' => 'Ŵ',
|
65
|
+
'X' => 'Ẋ',
|
66
|
+
'Y' => 'Ŷ',
|
67
|
+
'Z' => 'Ż',
|
68
|
+
}.freeze
|
69
|
+
|
70
|
+
class << self
|
71
|
+
def pseudolocalize(object)
|
72
|
+
translate_object(object)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def translate_object(object)
|
78
|
+
if object.is_a?(Hash)
|
79
|
+
object.transform_values { |value| translate_object(value) }
|
80
|
+
elsif object.is_a?(Array)
|
81
|
+
object.map { |value| translate_object(value) }
|
82
|
+
elsif object.is_a?(String)
|
83
|
+
translate_string(object)
|
84
|
+
else
|
85
|
+
object
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def translate_string(string)
|
90
|
+
|
91
|
+
string.split(ESCAPED_REGEX).map do |part|
|
92
|
+
if part =~ ESCAPED_REGEX
|
93
|
+
part
|
94
|
+
else
|
95
|
+
part.chars.map do |char|
|
96
|
+
if LETTERS.key?(char)
|
97
|
+
value = LETTERS[char]
|
98
|
+
value = value * 2 if VOWELS.include?(char)
|
99
|
+
value
|
100
|
+
else
|
101
|
+
char
|
102
|
+
end
|
103
|
+
end.join
|
104
|
+
end
|
105
|
+
end.join
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/pseudolocalization.gemspec
CHANGED
@@ -21,6 +21,6 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
|
-
spec.add_development_dependency "rake", "~>
|
24
|
+
spec.add_development_dependency "rake", "~> 12.3"
|
25
25
|
spec.add_development_dependency "minitest", "~> 5.0"
|
26
26
|
end
|
data/service.yml
ADDED
data/shipit.yml
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pseudolocalization
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Blais
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '12.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '12.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: minitest
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,6 +45,7 @@ executables: []
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
+
- ".dependabot/config.yml"
|
48
49
|
- ".gitignore"
|
49
50
|
- ".travis.yml"
|
50
51
|
- Gemfile
|
@@ -54,11 +55,12 @@ files:
|
|
54
55
|
- Rakefile
|
55
56
|
- bin/console
|
56
57
|
- bin/setup
|
57
|
-
- circle.yml
|
58
58
|
- dev.yml
|
59
59
|
- lib/pseudolocalization.rb
|
60
|
+
- lib/pseudolocalization/pseudolocalizer.rb
|
60
61
|
- lib/pseudolocalization/version.rb
|
61
62
|
- pseudolocalization.gemspec
|
63
|
+
- service.yml
|
62
64
|
- shipit.yml
|
63
65
|
homepage: https://github.com/Shopify/pseudolocalization
|
64
66
|
licenses:
|
@@ -80,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
82
|
version: '0'
|
81
83
|
requirements: []
|
82
84
|
rubyforge_project:
|
83
|
-
rubygems_version: 2.
|
85
|
+
rubygems_version: 2.5.2.3
|
84
86
|
signing_key:
|
85
87
|
specification_version: 4
|
86
88
|
summary: Internationalization development tool
|
data/circle.yml
DELETED
@@ -1,15 +0,0 @@
|
|
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"
|