traduco 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,33 @@
1
+ Software License Agreement (BSD License)
2
+
3
+ Copyright (c) 2013, Joseph Earl
4
+ All rights reserved.
5
+
6
+ Copyright (c) 2012, Mobiata, LLC
7
+ All rights reserved.
8
+
9
+ Redistribution and use of this software in source and binary forms, with or
10
+ without modification, are permitted provided that the following conditions are
11
+ met:
12
+
13
+ * Redistributions of source code must retain the above copyright notice, this
14
+ list of conditions and the following disclaimer.
15
+
16
+ * Redistributions in binary form must reproduce the above copyright notice,
17
+ this list of conditions and the following disclaimer in the documentation
18
+ and/or other materials provided with the distribution.
19
+
20
+ * Neither the name of the organization nor the names of its contributors may be
21
+ used to endorse or promote products derived from this software without
22
+ specific prior written permission.
23
+
24
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
28
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,182 @@
1
+ # Traduco
2
+
3
+ Traduco is a command line tool for managing your strings and their translations. These strings are all stored in a master text file and then Traduco uses this file to import and export strings in a variety of file types, including iOS and Mac OS X `.strings` files, Android `.xml` files, gettext `.po` files, and [jquery-localize][jquerylocalize] `.json` files. This allows individuals and companies to easily share strings across multiple projects, as well as export strings in any format the user wants.
4
+
5
+ ## Install
6
+
7
+ ### As a Gem
8
+
9
+ Traduco is most easily installed as a Gem.
10
+
11
+ $ gem install traduco
12
+
13
+ ### From Source
14
+
15
+ You can also run Traduco directly from source. However, it requires [rubyzip][rubyzip] in order to create and read standard zip files.
16
+
17
+ $ gem install rubyzip
18
+ $ git clone git://github.com/mobiata/traduco.git
19
+ $ cd traduco
20
+ $ ./traduco --help
21
+
22
+ Make sure you run the `traduco` executable at the root of the project as it properly sets up your Ruby library path. The `bin/traduco` executable does not.
23
+
24
+ ## String File Format
25
+
26
+ Traduco stores all of its strings in a single file. The format of this file is a slight variant of the [Git][git] config file format, which itself is based on the old [Windows INI file][INI] format. The entire file is broken up into sections, which are created by placing the section name between two pairs of square brackets. Sections are optional, but they are a recommended way of breaking your strings into smaller, more manageable chunks.
27
+
28
+ Each grouping section contains N string definitions. These string definitions start with the string key placed within a single pair of square brackets. This string definition then contains a number of key-value pairs, including a comment, a comma-separated list of tags (which are used by Traduco to select a subset of strings), and all of the translations.
29
+
30
+ ### Tags
31
+
32
+ Tags are used by Traduco as a way to only work with a subset of your strings at any given point in time. Each string can be assigned zero or more tags which are separated by commas. Tags are optional, though highly recommended. You can get a list of all strings currently missing tags by executing the `generate-report` command.
33
+
34
+ ### Whitespace
35
+
36
+ Whitepace in this file is mostly ignored. If you absolutely need to put spaces at the beginning or end of your translated string, you can wrap the entire string in a pair of `` ` `` characters. If your actual string needs to start *and* end with a grave accent, you can wrap it in another pair of `` ` `` characters. See the example, below.
37
+
38
+ ### Example
39
+
40
+ [[General]]
41
+ [yes]
42
+ en = Yes
43
+ es = Sí
44
+ fr = Oui
45
+ ja = はい
46
+ [no]
47
+ en = No
48
+ fr = Non
49
+ ja = いいえ
50
+
51
+ [[Errors]]
52
+ [path_not_found_error]
53
+ en = The file '%@' could not be found.
54
+ tags = app1,app6
55
+ comment = An error describing when a path on the filesystem could not be found.
56
+ [network_unavailable_error]
57
+ en = The network is currently unavailable.
58
+ tags = app1
59
+ comment = An error describing when the device can not connect to the internet.
60
+
61
+ [[Escaping Example]]
62
+ [list_item_separator]
63
+ en = `, `
64
+ tags = mytag
65
+ comment = A string that should be placed between multiple items in a list. For example: Red, Green, Blue
66
+ [grave_accent_quoted_string]
67
+ en = ``%@``
68
+ tags = myothertag
69
+ comment = This string will evaluate to `%@`.
70
+
71
+ ## Supported Output Formats
72
+
73
+ Traduco currently supports the following formats for outputting strings:
74
+
75
+ * [iOS and OS X String Resources][applestrings] (format: apple)
76
+ * [Android String Resources][androidstrings] (format: android)
77
+ * [Gettext PO Files][gettextpo] (format: gettext)
78
+ * [jquery-localize Language Files][jquerylocalize] (format: jquery)
79
+
80
+ If you would like to enable traduco to create language files in another format, create an appropriate formatter in `lib/traduco/formatters`.
81
+
82
+ ## Usage
83
+
84
+ Usage: traduco COMMAND STRINGS_FILE [INPUT_OR_OUTPUT_PATH] [--lang LANG1,LANG2...] [--tags TAG1,TAG2,TAG3...] [--format FORMAT]
85
+
86
+ ### Commands
87
+
88
+ #### `generate-string-file`
89
+
90
+ This command creates an Apple or Android strings file from the master strings data file.
91
+
92
+ $ traduco generate-string-file /path/to/strings.txt values-ja.xml --tags common,app1
93
+ $ traduco generate-string-file /path/to/strings.txt Localizable.strings --lang ja --tags mytag
94
+ $ traduco generate-string-file /path/to/strings.txt all-english.strings --lang en
95
+
96
+ #### `generate-all-string-files`
97
+
98
+ This command is a convenient way to call `generate-string-file` multiple times. It uses standard Mac OS X, iOS, and Android conventions to figure out exactly which files to create given a parent directory. For example, if you point it to a parent directory containing `en.lproj`, `fr.lproj`, and `ja.lproj` subdirectories, Traduco will create a `Localizable.strings` file of the appropriate language in each of them. This is often the command you will want to execute during the build phase of your project.
99
+
100
+ $ traduco generate-all-string-files /path/to/strings.txt /path/to/project/locales/directory --tags common,app1
101
+
102
+ #### `consume-string-file`
103
+
104
+ This command slurps all of the strings from a `.strings` or `.xml` file and incorporates the translated text into the master strings data file. This is a simple way to incorporate any changes made to a single file by one of your translators. It will only identify strings that already exist in the master data file.
105
+
106
+ $ traduco consume-string-file /path/to/strings.txt fr.strings
107
+ $ traduco consume-string-file /path/to/strings.txt Localizable.strings --lang ja
108
+ $ traduco consume-string-file /path/to/strings.txt es.xml
109
+
110
+ #### `consume-all-string-files`
111
+
112
+ This command reads in a folder containing many `.strings` or `.xml` files. These files should be in a standard folder hierarchy so that traduco knows the language of each file. When combined with the `--developer-language`, `--consume-comments`, and `--consume-all` flags, this command is a great way to create your initial strings data file from an existing iOS or Android project. Just make sure that you create a blank strings.txt file, first!
113
+
114
+ $ traduco consume-all-string-files strings.txt Resources/Locales --developer-language en --consume-all --consume-comments
115
+
116
+ #### `generate-loc-drop`
117
+
118
+ This command is a convenient way to generate a zip file containing files created by the `generate-string-file` command. It is often used for creating a single zip containing a large number of strings in all languages which you can then hand off to your translation team.
119
+
120
+ $ traduco generate-loc-drop /path/to/strings.txt LocDrop1.zip
121
+ $ traduco generate-loc-drop /path/to/strings.txt LocDrop2.zip --lang en,fr,ja,ko --tags common,app1
122
+
123
+ #### `consume-loc-drop`
124
+
125
+ This command is a convenient way of taking a zip file and executing the `consume-string-file` command on each file within the archive. It is most often used to incorporate all of the changes made by the translation team after they have completed work on a localization drop.
126
+
127
+ $ traduco consume-loc-drop /path/to/strings.txt LocDrop2.zip
128
+
129
+ #### `generate-report`
130
+
131
+ This command gives you useful information about your strings. It will tell you how many strings you have, how many have been translated into each language, and whether your master strings data file has any duplicate string keys.
132
+
133
+ $ traduco generate-report /path/to/strings.txt
134
+
135
+ ## Creating Your First strings.txt File
136
+
137
+ The easiest way to create your first strings.txt file is to run the `consume-all-string-files` command. The one caveat is to first create a blank strings.txt file to use as your starting point. Then, just point the `consume-all-string-files` command at a directory in your project containing all of your iOS, OS X, or Android strings files.
138
+
139
+ $ touch strings.txt
140
+ $ traduco consume-all-string-files strings.txt Resources/Locales --developer-language en --consume-all --consume-comments
141
+
142
+ ## Traduco and Your Build Process
143
+
144
+ It is easy to incorporate Traduco right into your iOS and OS X app build processes.
145
+
146
+ 1. In your project folder, create all of the `.lproj` directories that you need. It does not really matter where they are. We tend to put them in `Resources/Locales/`.
147
+ 2. Run the `generate-all-string-files` command to create all of the string files you need in these directories. For example,
148
+
149
+ $ traduco generate-all-string-files strings.txt Resources/Locales/ --tags tag1,tag2
150
+
151
+ Make sure you point Traduco at your strings data file, the directory that contains all of your `.lproj` directories, and the tags that describe the strings you want to use for this project.
152
+ 3. Drag the `Resources/Locales/` directory to the Xcode project navigator so that Xcode knows to include all of these strings files in your build.
153
+ 4. In Xcode, navigate to the "Build Phases" tab of your target.
154
+ 5. Click on the "Add Build Phase" button and select "Add Run Script".
155
+ 6. Drag the new "Run Script" build phase up so that it runs earlier in the build process. It doesn't really matter where, as long as it happens before the resources are copied to your bundle.
156
+ 7. Edit your script to run the exact same command you ran in step (2) above.
157
+
158
+ Now, whenever you build your application, Xcode will automatically invoke Traduco to make sure that your `.strings` files are up-to-date.
159
+
160
+ ## User Interface
161
+
162
+ * [Traduco TextMate 2 Bundle](https://github.com/mobiata/traduco.tmbundle) — This [TextMate 2](https://github.com/textmate/textmate) bundle will make it easier for you to work with Traduco strings files. In particular, it lets you use code folding to easily collapse and expand both strings and sections.
163
+ * [traduco_ui](https://github.com/Daij-Djan/traduco_ui) — A user interface for Traduco written by [Dominik Pich](https://github.com/Daij-Djan/). Consider using this if you would prefer to use Traduco without dropping to a command line.
164
+
165
+ ## Contributors
166
+
167
+ Many thanks to all of the contributors to the Traduco project, including:
168
+
169
+ * [Ishitoya Kentaro](https://github.com/kent013)
170
+ * [Kevin Everets](https://github.com/keverets)
171
+ * [Kevin Wood](https://github.com/kwood)
172
+ * [Mohammad Hejazi](https://github.com/MohammadHejazi)
173
+ * [Robert Guo](http://www.robertguo.me/)
174
+
175
+
176
+ [rubyzip]: http://rubygems.org/gems/rubyzip
177
+ [git]: http://git-scm.org/
178
+ [INI]: http://en.wikipedia.org/wiki/INI_file
179
+ [applestrings]: http://developer.apple.com/documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html
180
+ [androidstrings]: http://developer.android.com/guide/topics/resources/string-resource.html
181
+ [gettextpo]: http://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/PO-Files.html
182
+ [jquerylocalize]: https://github.com/coderifous/jquery-localize
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ require 'twine'
3
+ begin
4
+ Twine::Runner.run(ARGV)
5
+ rescue Twine::Error => e
6
+ STDERR.puts e.message
7
+ exit
8
+ end
@@ -0,0 +1,10 @@
1
+ module Traduco
2
+ class Error < StandardError
3
+ end
4
+
5
+ require 'traduco/cli'
6
+ require 'traduco/encoding'
7
+ require 'traduco/formatters'
8
+ require 'traduco/runner'
9
+ require 'traduco/l10nfile'
10
+ end
@@ -0,0 +1,186 @@
1
+ require 'optparse'
2
+
3
+ module Traduco
4
+ class CLI
5
+ def initialize(args, options)
6
+ @options = options
7
+ @args = args
8
+ end
9
+
10
+ def self.parse_args(args, options)
11
+ new(args, options).parse_args
12
+ end
13
+
14
+ def parse_args
15
+ parser = OptionParser.new do |opts|
16
+ opts.banner = 'Usage: twine COMMAND STRINGS_FILE [INPUT_OR_OUTPUT_PATH] [--lang LANG1,LANG2...] [--tags TAG1,TAG2,TAG3...] [--format FORMAT]'
17
+ opts.separator ''
18
+ opts.separator 'The purpose of this script is to convert back and forth between multiple data formats, allowing us to treat our strings (and translations) as data stored in a text file. We can then use the data file to create drops for the localization team, consume similar drops returned by the localization team, generate reports on the strings, as well as create formatted string files to ship with your products. Traduco currently supports iOS, OS X, Android, gettext, and jquery-localize string files.'
19
+ opts.separator ''
20
+ opts.separator 'Commands:'
21
+ opts.separator ''
22
+ opts.separator 'generate-string-file -- Generates a string file in a certain LANGUAGE given a particular FORMAT. This script will attempt to guess both the language and the format given the filename and extension. For example, "ko.xml" will generate a Korean language file for Android.'
23
+ opts.separator ''
24
+ opts.separator 'generate-all-string-files -- Generates all the string files necessary for a given project. The parent directory to all of the locale-specific directories in your project should be specified as the INPUT_OR_OUTPUT_PATH. This command will most often be executed by your build script so that each build always contains the most recent strings.'
25
+ opts.separator ''
26
+ opts.separator 'consume-string-file -- Slurps all of the strings from a translated strings file into the specified STRINGS_FILE. If you have some files returned to you by your translators you can use this command to incorporate all of their changes. This script will attempt to guess both the language and the format given the filename and extension. For example, "ja.strings" will assume that the file is a Japanese iOS strings file.'
27
+ opts.separator ''
28
+ opts.separator 'consume-all-string-files -- Slurps all of the strings from a directory into the specified STRINGS_FILE. If you have some files returned to you by your translators you can use this command to incorporate all of their changes. This script will attempt to guess both the language and the format given the filename and extension. For example, "ja.strings" will assume that the file is a Japanese iOS strings file.'
29
+ opts.separator ''
30
+ opts.separator 'generate-loc-drop -- Generates a zip archive of strings files in any format. The purpose of this command is to create a very simple archive that can be handed off to a translation team. The translation team can unzip the archive, translate all of the strings in the archived files, zip everything back up, and then hand that final archive back to be consumed by the consume-loc-drop command. This command assumes that --include-untranslated has been specified on the command line.'
31
+ opts.separator ''
32
+ opts.separator 'consume-loc-drop -- Consumes an archive of translated files. This archive should be in the same format as the one created by the generate-loc-drop command.'
33
+ opts.separator ''
34
+ opts.separator 'generate-report -- Generates a report containing data about your strings. For example, it will tell you if you have any duplicate strings or if any of your strings are missing tags. In addition, it will tell you how many strings you have and how many of those strings have been translated into each language.'
35
+ opts.separator ''
36
+ opts.separator 'General Options:'
37
+ opts.separator ''
38
+ opts.on('-l', '--lang LANGUAGES', Array, 'The language code(s) to use for the specified action.') do |langs|
39
+ @options[:languages] = langs
40
+ end
41
+ opts.on('-t', '--tags TAGS', Array, 'The tag(s) to use for the specified action. Only strings with that tag will be processed. Do not specify any tags to match all strings in the strings data file.') do |tags|
42
+ @options[:tags] = tags
43
+ end
44
+ opts.on('-u', '--untagged', 'If you have specified tags using the --tags flag, then only those tags will be selected. If you also want to select all strings that are untagged, then you can specify this option to do so.') do |u|
45
+ @options[:untagged] = true
46
+ end
47
+ formats = []
48
+ Formatters::FORMATTERS.each do |formatter|
49
+ formats << formatter::FORMAT_NAME
50
+ end
51
+ opts.on('-f', '--format FORMAT', "The file format to read or write (#{formats.join(', ')}). Additional formatters can be placed in the formats/ directory.") do |format|
52
+ lformat = format.downcase
53
+ if !formats.include?(lformat)
54
+ STDERR.puts "Invalid format: #{format}"
55
+ end
56
+ @options[:format] = lformat
57
+ end
58
+ opts.on('-a', '--consume-all', 'Normally, when consuming a string file, Traduco will ignore any string keys that do not exist in your master file.') do |a|
59
+ @options[:consume_all] = true
60
+ end
61
+ opts.on('-s', '--include-untranslated', 'This flag will cause any Android string files that are generated to include strings that have not yet been translated for the current language.') do |s|
62
+ @options[:include_untranslated] = true
63
+ end
64
+ opts.on('-o', '--output-file OUTPUT_FILE', 'Write the new strings database to this file instead of replacing the original file. This flag is only useful when running the consume-string-file or consume-loc-drop commands.') do |o|
65
+ @options[:output_path] = o
66
+ end
67
+ opts.on('-n', '--file-name FILE_NAME', 'When running the generate-all-string-files command, this flag may be used to overwrite the default file name of the format.') do |n|
68
+ @options[:file_name] = n
69
+ end
70
+ opts.on('-d', '--developer-language LANG', 'When writing the strings data file, set the specified language as the "developer language". In practice, this just means that this language will appear first in the strings data file.') do |d|
71
+ @options[:developer_language] = d
72
+ end
73
+ opts.on('-c', '--consume-comments', 'Normally, when consuming a string file, Traduco will ignore all comments in the file. With this flag set, any comments encountered will be read and parsed into the strings data file. This is especially useful when creating your first strings data file from an existing project.') do |c|
74
+ @options[:consume_comments] = true
75
+ end
76
+ opts.on('-e', '--encoding ENCODING', 'Traduco defaults to encoding all output files in UTF-8. This flag will tell Traduco to use an alternate encoding for these files. For example, you could use this to write Apple .strings files in UTF-16. This flag currently only works with Apple .strings files and is currently only supported in Ruby 1.9.3 or greater.') do |e|
77
+ if !"".respond_to?(:encode)
78
+ raise Traduco::Error.new "The --encoding flag is only supported on Ruby 1.9.3 or greater."
79
+ end
80
+ @options[:output_encoding] = e
81
+ end
82
+ opts.on('-h', '--help', 'Show this message.') do |h|
83
+ puts opts.help
84
+ exit
85
+ end
86
+ opts.on('--version', 'Print the version number and exit.') do |x|
87
+ puts "Traduco version #{Traduco::VERSION}"
88
+ exit
89
+ end
90
+ opts.separator ''
91
+ opts.separator 'Examples:'
92
+ opts.separator ''
93
+ opts.separator '> twine generate-string-file strings.txt ko.xml --tags FT'
94
+ opts.separator '> twine generate-all-string-files strings.txt Resources/Locales/ --tags FT,FB'
95
+ opts.separator '> twine consume-string-file strings.txt ja.strings'
96
+ opts.separator '> twine consume-all-string-files strings.txt Resources/Locales/ --developer-language en'
97
+ opts.separator '> twine generate-loc-drop strings.txt LocDrop5.zip --tags FT,FB --format android --lang de,en,en-GB,ja,ko'
98
+ opts.separator '> twine consume-loc-drop strings.txt LocDrop5.zip'
99
+ opts.separator '> twine generate-report strings.txt'
100
+ end
101
+ parser.parse! @args
102
+
103
+ if @args.length == 0
104
+ puts parser.help
105
+ exit
106
+ end
107
+
108
+ @options[:command] = @args[0]
109
+
110
+ if !VALID_COMMANDS.include? @options[:command]
111
+ raise Traduco::Error.new "Invalid command: #{@options[:command]}"
112
+ end
113
+
114
+ if @args.length == 1
115
+ raise Traduco::Error.new 'You must specify your strings file.'
116
+ end
117
+
118
+ @options[:strings_file] = @args[1]
119
+
120
+ case @options[:command]
121
+ when 'generate-string-file'
122
+ if @args.length == 3
123
+ @options[:output_path] = @args[2]
124
+ elsif @args.length > 3
125
+ raise Traduco::Error.new "Unknown argument: #{@args[3]}"
126
+ else
127
+ raise Traduco::Error.new 'Not enough arguments.'
128
+ end
129
+ if @options[:languages] and @options[:languages].length > 1
130
+ raise Traduco::Error.new 'Please only specify a single language for the generate-string-file command.'
131
+ end
132
+ when 'generate-all-string-files'
133
+ if ARGV.length == 3
134
+ @options[:output_path] = @args[2]
135
+ elsif @args.length > 3
136
+ raise Traduco::Error.new "Unknown argument: #{@args[3]}"
137
+ else
138
+ raise Traduco::Error.new 'Not enough arguments.'
139
+ end
140
+ when 'consume-string-file'
141
+ if @args.length == 3
142
+ @options[:input_path] = @args[2]
143
+ elsif @args.length > 3
144
+ raise Traduco::Error.new "Unknown argument: #{@args[3]}"
145
+ else
146
+ raise Traduco::Error.new 'Not enough arguments.'
147
+ end
148
+ if @options[:languages] and @options[:languages].length > 1
149
+ raise Traduco::Error.new 'Please only specify a single language for the consume-string-file command.'
150
+ end
151
+ when 'consume-all-string-files'
152
+ if @args.length == 3
153
+ @options[:input_path] = @args[2]
154
+ elsif @args.length > 3
155
+ raise Traduco::Error.new "Unknown argument: #{@args[3]}"
156
+ else
157
+ raise Traduco::Error.new 'Not enough arguments.'
158
+ end
159
+ when 'generate-loc-drop'
160
+ @options[:include_untranslated] = true
161
+ if @args.length == 3
162
+ @options[:output_path] = @args[2]
163
+ elsif @args.length > 3
164
+ raise Traduco::Error.new "Unknown argument: #{@args[3]}"
165
+ else
166
+ raise Traduco::Error.new 'Not enough arguments.'
167
+ end
168
+ if !@options[:format]
169
+ raise Traduco::Error.new 'You must specify a format.'
170
+ end
171
+ when 'consume-loc-drop'
172
+ if @args.length == 3
173
+ @options[:input_path] = @args[2]
174
+ elsif @args.length > 3
175
+ raise Traduco::Error.new "Unknown argument: #{@args[3]}"
176
+ else
177
+ raise Traduco::Error.new 'Not enough arguments.'
178
+ end
179
+ when 'generate-report'
180
+ if @args.length > 2
181
+ raise Traduco::Error.new "Unknown argument: #{@args[2]}"
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,20 @@
1
+ module Traduco
2
+ module Encoding
3
+ def self.encoding_for_path path
4
+ File.open(path, 'rb') do |f|
5
+ begin
6
+ a = f.readbyte
7
+ b = f.readbyte
8
+ if (a == 0xfe && b == 0xff)
9
+ return 'UTF-16BE'
10
+ elsif (a == 0xff && b == 0xfe)
11
+ return 'UTF-16LE'
12
+ end
13
+ rescue EOFError
14
+ end
15
+ end
16
+
17
+ 'UTF-8'
18
+ end
19
+ end
20
+ end