applyrics 0.0.2 → 0.0.3.pre

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b4ca2e8f98970107cda93dab4aa1319ce15eec97
4
- data.tar.gz: e5273c52d624cb091b1d062ee342b03650dbf308
3
+ metadata.gz: 7f8c09970f5298b306a1f05ff6c89f36fb8db206
4
+ data.tar.gz: d7226737efbd8949a1e5eaa135809d7a20457251
5
5
  SHA512:
6
- metadata.gz: 0eb761243e8dbd25564b16d3c5cee3e2aa67834d1adfed9c55ce3c3d33a67286a09502f97aaabe7489388c919740085ef2a110777fa213db121e783586d6443a
7
- data.tar.gz: 866a96e777269425eab3eb6750fb747e2572a48b96d2f0db6f4dae668c266517edf28882a76ac74467839c69a513082c5cef041a095831b5ff9d2881a1e4db4b
6
+ metadata.gz: 9c05ad2a2ee39d8854a7487f96ac1efaa4e70c4f7c828df7a8785a547a43bd430f0d7ca1f6a6eb629009e1cc218e6d03fa3359ac2f8489d2a5e35d1872a92180
7
+ data.tar.gz: a65d253e07a1cf8a45e2a9362073b9bc7114344321869cf47684583591bf58e3e0488854f62a8f0b4b5f917c091a3f569d4839e4903bf86f898aaece54f0abdb
data/README.md CHANGED
@@ -8,49 +8,64 @@ Manage your localization with confidence.
8
8
 
9
9
  ## Disclaimer
10
10
 
11
- ---
12
- This software should be considered ***pre-alpha*** and may thus be incomplete and contain bugs.
13
- ---
11
+ **This software should be considered _pre-alpha_ and may thus change at any time, be incomplete or contain bugs.**
12
+
13
+ ## Why Applyrics?
14
+
15
+ Managing translations for mobile projects can be a mess, especially if you are working with multiple platforms.
16
+ iOS projects use key-value \*.strings files, Android use xmls, and variables are defined differently.
17
+
18
+ *Applyrics* removes these obstacles and lets you manage languages using unified json files.
14
19
 
15
20
  ## Status
16
21
 
17
22
  | Feature | iOS | Android |
18
23
  | --------- | --- | --------|
19
- | init | :x: | :x: |
20
- | rebuild | :x: | :x: |
24
+ | extract | :x: | :x: |
21
25
  | apply | :x: | :x: |
22
- | sync | :x: | :x: |
23
26
 
24
27
  ## Installation
25
28
 
26
29
  Install using ruby gems:
27
30
 
28
- sudo gem install applyrics --verbose
31
+ sudo gem install applyrics --verbose
29
32
 
30
33
 
31
34
  ## Usage
32
35
 
33
- Initialize
34
- (iOS: :x: Android: :x:)
36
+ Usually you start out by extracting the strings from an existing project into a json file by running the following command in your projects directory:
35
37
 
36
- applyrics init
38
+ applyrics extract
37
39
 
38
40
 
39
- Rebuild language files
40
- (iOS: :x: Android: :x:)
41
+ After you've made changes to the translations you can apply those changes to the projects.
42
+ Notice the addition of the *--rebuild* flag. This will ensure that we don't miss any new keys that might have been added.
41
43
 
42
- applyrics rebuild
44
+ applyrics apply --rebuild
43
45
 
44
46
 
45
- Apply a json language file
47
+ ### Global flags
48
+
49
+ | Flag | Default | Description |
50
+ | --------------- | ------- | ---------------------------- |
51
+ | --verbose | false | Output more detailed logs |
52
+ | --rebuild | false | Rebuilds strings from source |
53
+ | --lang CODE | *All* | Language to work with |
54
+ | --project PATH | "./" | Path to project |
55
+
56
+
57
+ ### Actions
58
+
59
+ Extract strings from project and create strings.json file
46
60
  (iOS: :x: Android: :x:)
47
61
 
48
- applyrics apply
62
+ applyrics extract
49
63
 
50
- Sync languages
64
+
65
+ Apply a json language file
51
66
  (iOS: :x: Android: :x:)
52
67
 
53
- applyrics sync
68
+ applyrics apply
54
69
 
55
70
 
56
71
  ## License
@@ -1,5 +1,7 @@
1
1
  require 'commander'
2
+ require 'colored'
2
3
  require 'applyrics/setup'
4
+ require 'applyrics/languagefile'
3
5
 
4
6
  module Applyrics
5
7
  class CLI
@@ -14,48 +16,80 @@ module Applyrics
14
16
  program :version, Applyrics::VERSION
15
17
  program :description, Applyrics::DESCRIPTION
16
18
  program :help_formatter, :compact
19
+ global_option '--project PATH', String, 'Path to iOS or Android project'
20
+ global_option '--[no-]rebuild', TrueClass, 'Rebuild language files from source'
21
+ global_option '--lang CODE', String, 'Only perform the action for the specified language'
17
22
 
18
23
  command :init do |c|
19
24
  c.syntax = "applyrics init"
20
- c.description = "Sets up the project"
25
+ c.description = "Setup the project for applyrics"
21
26
  c.action do |args, options|
22
- puts "Not implemented yet... Sorry!"
27
+ project = Applyrics::Project.new()
28
+
29
+ if project.nil?
30
+ puts "Error"
31
+ else
32
+ case project.platform
33
+ when :ios
34
+ puts "Located ".green + "iOS".bold.green + " project".green
35
+ when :android
36
+ puts "Located ".green + "Android".bold.green + " project".green
37
+ end
38
+
39
+ langs = project.detected_languages
40
+ puts "Found #{langs.length} languages: #{langs.join(', ')}".green
41
+ puts ""
42
+
43
+ lang_files = project.language_files
44
+ langs.each do |lang|
45
+ if !lang_files.key?(lang)
46
+ puts "[#{lang}] No files detected for language!".yellow
47
+ next
48
+ end
49
+ end
50
+
51
+ end
23
52
  end
24
53
  end
25
54
 
26
- command :rebuild do |c|
27
- c.syntax = "applyrics rebuild"
28
- c.description = "Rebuilds language files for your project"
29
- c.option '--project STRING', String, 'Path to iOS or Android project'
55
+ command :extract do |c|
56
+ c.syntax = "applyrics extract"
57
+ c.description = "Pull strings from the project into a strings.json file"
58
+ c.option '--force-split', TrueClass, 'Saves one language file per language instead of a single one for all languages'
30
59
  c.action do |args, options|
31
- options.default :project => './'
32
- puts "rebuilding..."
60
+
33
61
  project = Applyrics::Project.new()
34
- project.rebuild_files()
62
+ detect_lang = project.detected_languages
63
+
64
+ langs = project.string_files()
65
+
66
+ puts "Found files for #{langs.length} languages".green
67
+
68
+ if options.rebuild
69
+ puts "Rebuilding...".blue
70
+ rebuilt = project.rebuild_files()
71
+ langs = langs.merge(rebuilt)
72
+ puts "Language \"#{project.default_language}\" is rebuilt from source into #{rebuilt[project.default_language].length} files".blue
73
+ end
74
+
75
+ puts "Writing #{langs.length} languages: #{langs.keys.join(', ')}".green
76
+
77
+ file = LanguageFile.new(File.join("./", "strings.json"), langs)
78
+ file.write
79
+
35
80
  end
36
81
  end
37
82
 
38
83
  command :apply do |c|
39
84
  c.syntax = "applyrics apply"
40
85
  c.description = "Applies language from a .json file"
41
- c.option '--project STRING', String, 'Path to iOS or Android project'
42
- c.option '--data STRING', String, 'Path to .json file (Default: lyrics.json)'
86
+ c.option '--data STRING', String, 'Path to .json file (Default: strings.json)'
43
87
  c.action do |args, options|
44
88
  options.default :project => './', :data => './lyrics.json'
45
89
  puts "Not implemented yet... Sorry!"
46
90
  end
47
91
  end
48
92
 
49
- command :sync do |c|
50
- c.syntax = "applyrics sync"
51
- c.description = "Syncs language from applyrics.io"
52
- c.option '--project STRING', String, 'Path to iOS or Android project'
53
- c.action do |args, options|
54
- options.default :project => './'
55
- puts "Not implemented yet... Sorry!"
56
- end
57
- end
58
-
59
93
  run!
60
94
  end
61
95
  end
@@ -49,7 +49,7 @@ module Applyrics
49
49
  status = $?.exitstatus
50
50
  if status != 0
51
51
  o = output.join("\n")
52
- puts o
52
+ puts "Status #{status} - #{o}"
53
53
  end
54
54
 
55
55
  return output.join("\n")
@@ -1,4 +1,4 @@
1
1
  module Applyrics
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3.pre"
3
3
  DESCRIPTION = "Handle localization for all your mobile projects"
4
4
  end
@@ -0,0 +1,42 @@
1
+ require 'multi_json'
2
+
3
+ # encoding=utf-8
4
+ module Applyrics
5
+ class LanguageFile
6
+
7
+ def initialize(path, data=nil)
8
+ @path = path
9
+ @hash = data
10
+ if data.nil?
11
+ read
12
+ end
13
+ end
14
+
15
+ def [](key)
16
+ @hash[key]
17
+ end
18
+
19
+ def []=(key, value)
20
+ @hash[key] = value
21
+ end
22
+
23
+ def language?(key)
24
+ @hash.key?(key)
25
+ end
26
+
27
+ def languages
28
+ @hash.keys
29
+ end
30
+
31
+ def read
32
+ @hash = {}
33
+ data = File.read(@path)
34
+ @hash = MultiJson.load(data)
35
+ end
36
+
37
+ def write()
38
+ File.open(@path, 'w') { |file| file.write(MultiJson.dump(@hash, :pretty => true)) }
39
+ end
40
+
41
+ end
42
+ end
@@ -47,15 +47,33 @@ module Applyrics
47
47
  @project.detected_languages()
48
48
  end
49
49
 
50
+ def language_files
51
+ @project.language_files()
52
+ end
53
+
54
+ # @return [String] The language which are the default language in the project
55
+ def default_language
56
+ @project.default_language
57
+ end
58
+
50
59
  # @param [String] the name of the setting to read.
51
60
  # @return [String, nil] the value of the setting or nil if not found.
52
61
  def platform_project_settings(name)
53
62
  @project.platform_project_settings(name)
54
63
  end
55
64
 
65
+ # @return [Object, nil] the strings files found in the project
66
+ def string_files
67
+ @project.string_files()
68
+ end
69
+
56
70
  # Rebuild the language files.
57
71
  def rebuild_files
58
72
  @project.rebuild_files()
59
73
  end
74
+
75
+ def platform
76
+ @platform
77
+ end
60
78
  end
61
79
  end
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
  require 'i18n_data'
3
3
  require 'multi_json'
4
+ require 'fileutils'
4
5
  require 'applyrics/tools/genstrings'
5
6
  require 'applyrics/tools/ibtool'
6
7
  require 'applyrics/stringsfile'
@@ -15,22 +16,47 @@ module Applyrics
15
16
  end
16
17
  @path = path
17
18
  @platform_settings = nil
18
- @langs = {}
19
+ @langs = []
20
+ @default_language = nil
19
21
  end
20
22
 
21
23
  # Return a list of detected languages in the project
22
24
  def detected_languages
25
+ @langs = []
23
26
  folder = self.platform_project_settings("SOURCE_ROOT")
24
- base_language = I18nData.language_code(self.platform_project_settings("DEVELOPMENT_LANGUAGE")).downcase
25
27
  lang_folders = Dir.glob(File.join(folder, "**", "*.lproj"))
26
28
  lang_folders.each do |lang_folder|
27
29
  lang = /([A-Za-z\-]*?)\.lproj/.match(lang_folder)[1]
28
- lang = (lang == "Base" ? base_language : lang)
29
- @langs[lang] = lang_folder
30
+ lang = (lang == "Base" ? default_language : lang)
31
+ @langs << lang
30
32
  end
31
33
  return @langs
32
34
  end
33
35
 
36
+ def language_files
37
+ folder = self.platform_project_settings("SOURCE_ROOT") unless !folder.nil?
38
+ out = {}
39
+ Dir[File.join(folder, "**","*.strings")].each do |file|
40
+ lang = /(\w*).lproj/.match(file)[1]
41
+ lang = (lang == "Base" ? default_language : lang)
42
+
43
+ if !out.key?(lang)
44
+ out[lang] = []
45
+ end
46
+
47
+ out[lang] << file
48
+ end
49
+
50
+ out
51
+ end
52
+
53
+ def default_language
54
+ if @default_language.nil?
55
+ @default_language = I18nData.language_code(self.platform_project_settings("DEVELOPMENT_LANGUAGE")).downcase
56
+ end
57
+ @default_language
58
+ end
59
+
34
60
  def platform_project_settings(name)
35
61
  if @platform_settings.nil?
36
62
  cmd = ["set -o pipefail && xcrun xcodebuild -showBuildSettings"]
@@ -42,9 +68,29 @@ module Applyrics
42
68
  return result.split(" = ").last
43
69
  end
44
70
 
71
+ def string_files(folder=nil)
72
+ folder = self.platform_project_settings("SOURCE_ROOT") unless !folder.nil?
73
+
74
+ out = {}
75
+
76
+ Dir[File.join(folder, "**", "*.lproj", "*.strings")].each do |file|
77
+ strings = StringsFile.new(file)
78
+ lang = /(\w*).lproj/.match(file)[1]
79
+
80
+ if !out.key?(lang)
81
+ out[lang] = {}
82
+ end
83
+
84
+ out[lang][File.basename(file)] = strings.hash
85
+ end
86
+
87
+ out
88
+ end
89
+
90
+ # NOTE: This will only rebuild the base language
45
91
  def rebuild_files
46
92
  folder = self.platform_project_settings("SOURCE_ROOT")
47
- tmp_folder = "./.tmp/"
93
+ tmp_folder = "./tmp/"
48
94
 
49
95
  if !Dir.exist?(tmp_folder)
50
96
  Dir.mkdir(tmp_folder, 0700)
@@ -53,16 +99,18 @@ module Applyrics
53
99
  GenStrings.run("#{folder}", tmp_folder)
54
100
  IBTool.run("#{folder}", tmp_folder)
55
101
 
56
- out = {}
102
+ lang = default_language
103
+ out = {"#{lang}" => {}}
104
+ langHash = out["#{lang}"]
105
+
57
106
  Dir[File.join(tmp_folder, "*.strings")].each do |file|
58
- puts file
59
107
  strings = StringsFile.new(file)
60
- out[File.basename(file)] = strings.hash
108
+ langHash[File.basename(file)] = strings.hash
61
109
  end
62
110
 
63
- File.open(File.join("./", "strings.json"), 'w') { |file| file.write(MultiJson.dump(out, :pretty => true)) }
64
-
111
+ FileUtils.remove_dir(tmp_folder)
65
112
 
113
+ out
66
114
  end
67
115
  end
68
116
  end
@@ -2,9 +2,9 @@
2
2
  module Applyrics
3
3
  class StringsFile
4
4
 
5
- def initialize(filename, data=nil)
6
- @filename = filename
7
- @hash = data.nil? ? {} : data
5
+ def initialize(path, data=nil)
6
+ @path = path
7
+ @hash = data
8
8
  if data.nil?
9
9
  read
10
10
  end
@@ -13,7 +13,7 @@ module Applyrics
13
13
  def read
14
14
  @hash = {}
15
15
  parser = Parser.new(@hash)
16
- File.open(@filename, 'rb:utf-16LE:utf-8') { |fd| parser.parse fd }
16
+ File.open(@path, 'rb:bom|utf-16LE:utf-8') { |fd| parser.parse fd }
17
17
  self
18
18
  end
19
19
 
@@ -44,16 +44,8 @@ module Applyrics
44
44
 
45
45
  def parse(data)
46
46
  @hash.clear
47
- found_bad_bytes = false
48
47
  data.each_line do |line|
49
48
  @line = line.chomp
50
- if !found_bad_bytes
51
- first_bytes = @line[0..1].bytes.to_a
52
- if first_bytes.length == 2 && first_bytes[0] == 255
53
- @line = @line[2,@line.length].force_encoding('UTF-8')
54
- found_bad_bytes = true
55
- end
56
- end
57
49
 
58
50
  case @line
59
51
  when @comment_regex
@@ -15,7 +15,7 @@ module Applyrics
15
15
  cmd << "-o " + Shellwords.escape("#{output_folder}")
16
16
  cmd << Shellwords.join(files(folder))
17
17
 
18
- puts Command.execute(cmd)
18
+ Command.execute(cmd)
19
19
  end
20
20
 
21
21
  def files(folder)
@@ -19,7 +19,7 @@ module Applyrics
19
19
  cmd << Command.which("ibtool")
20
20
  cmd << "--export-strings-file " + Shellwords.escape("#{output_file}")
21
21
  cmd << Shellwords.escape("#{file}")
22
- puts Command.execute(cmd)
22
+ Command.execute(cmd)
23
23
  end
24
24
  end
25
25
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: applyrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frederik Wallner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-28 00:00:00.000000000 Z
11
+ date: 2016-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commander
@@ -125,6 +125,7 @@ files:
125
125
  - lib/applyrics/command.rb
126
126
  - lib/applyrics/environment.rb
127
127
  - lib/applyrics/info.rb
128
+ - lib/applyrics/languagefile.rb
128
129
  - lib/applyrics/lyricsfile.rb
129
130
  - lib/applyrics/project.rb
130
131
  - lib/applyrics/project_ios.rb
@@ -141,8 +142,10 @@ files:
141
142
  homepage: https://github.com/applyrics/applyrics-gem
142
143
  licenses:
143
144
  - MIT
144
- metadata: {}
145
- post_install_message:
145
+ metadata:
146
+ issue_tracker: https://github.com/applyrics/applyrics-gem/issues
147
+ post_install_message: Thank you for using applyrics! Please keep in mind that this
148
+ software is in early development, things might break.
146
149
  rdoc_options: []
147
150
  require_paths:
148
151
  - lib
@@ -153,9 +156,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
153
156
  version: '0'
154
157
  required_rubygems_version: !ruby/object:Gem::Requirement
155
158
  requirements:
156
- - - '>='
159
+ - - '>'
157
160
  - !ruby/object:Gem::Version
158
- version: '0'
161
+ version: 1.3.1
159
162
  requirements: []
160
163
  rubyforge_project:
161
164
  rubygems_version: 2.0.14