class YARD::I18n::PotGenerator
GNU gettext manual about details of PO file
@see www.gnu.org/software/gettext/manual/html_node/PO-Files.html<br>end
pot_file.print(pot)
File.open(po_file_path, “w”) do |pot_file|
po_file_directory_pathname.mkpath
pot = generator.generate
generator.parse_files(files)
generator.parse_objects(objects)
generator = YARD::I18n::PotGenerator.new(relative_base_path)
# relative_base_path -> “..”
relative_base_path = working_directory_pathname.relative_path_from(po_file_directory_pathname).to_s
working_directory_pathname = Pathname.new(“.”)
po_file_directory_pathname = Pathname.new(po_file_path).directory)
po_file_path = “po/yard.pot”
@example Generate a .pot file
“po/yard.pot”.
working directory path is “.” and the POT is wrote into
file. The relative working directory path is “..” when the
objects, generate a POT and write the generated POT to a .pot
{CodeObjects::Base} objects and {CodeObjects::ExtraFileObject}
directory path that has created .pot file, parsePotGenerator
with a relative working directory path from a
To create a .pot file by PotGenerator
, instantiate a
== Usage
is extracted as a msgid.
{CodeObjects::ExtraFileObject} object is parsed and a paragraph
{CodeObjects::ExtraFileObject} objects. The file content of
{#parse_files} extracts msgids from
msgids from a tag.
extracted as a msgid. Tag name and tag text are extracted as
{CodeObjects::Base} object is parsed and a paragraph is
{CodeObjects::Base} objects. The docstring of
{#parse_objects} extracts msgids from docstring and tags of
* {#parse_files} for {CodeObjects::ExtraFileObject}
* {#parse_objects} for {CodeObjects::Base}
The PotGenerator
has two parse methods:
== How to extract msgids
msgstr. The extension for PO is “.po”.
“Bonjour” in French, “Hello” is the msgid ID and “Bonjour” is
of message ID. If you want to translate “Hello” in English into
message and message string (msgstr) that is translated message
many parts of message ID (msgid) that is translation target
“.pot”. PO file is an acronym for “Portable Object”. PO file has
template file to create PO file. The extension for POT is
POT is an acronym for “Portable Object Template”. POT is a
== POT and PO
{CodeObjects::Base} and {CodeObjects::ExtraFileObject}.
The PotGenerator
generates POT format string from
def current_time
def current_time @current_time ||= Time.now end
def escape_message_id(message_id)
def escape_message_id(message_id) message_id.gsub(/(\\|")/) do special_character = $1 "\\#{special_character}" end end
def extract_documents(object)
def extract_documents(object) return if @extracted_objects.key?(object) @extracted_objects[object] = true case object when CodeObjects::NamespaceObject object.children.each do |child| extract_documents(child) end end if object.group message = register_message(object.group) object.files.each do |path, line| message.add_location(path, line) end message.add_comment(object.path) unless object.path.empty? end docstring = object.docstring unless docstring.empty? text = Text.new(StringIO.new(docstring)) text.extract_messages do |type, *args| case type when :paragraph paragraph, line_no = *args message = register_message(paragraph.rstrip) object.files.each do |path, line| message.add_location(path, (docstring.line || line) + line_no) end message.add_comment(object.path) unless object.path.empty? else raise "should not reach here: unexpected type: #{type}" end end end docstring.tags.each do |tag| extract_tag_documents(tag) end end
def extract_paragraphs(file)
def extract_paragraphs(file) File.open(file.filename) do |input| text = Text.new(input, :have_header => true) text.extract_messages do |type, *args| case type when :attribute name, value, line_no = *args message = register_message(value) message.add_location(file.filename, line_no) message.add_comment(name) when :paragraph paragraph, line_no = *args message = register_message(paragraph.rstrip) message.add_location(file.filename, line_no) else raise "should not reach here: unexpected type: #{type}" end end end end
def extract_tag_documents(tag)
def extract_tag_documents(tag) extract_tag_name(tag) extract_tag_text(tag) extract_documents(tag) if Tags::OverloadTag === tag end
def extract_tag_name(tag)
def extract_tag_name(tag) return if tag.name.nil? return if tag.name.is_a?(String) && tag.name.empty? key = "tag|#{tag.tag_name}|#{tag.name}" message = register_message(key) tag.object.files.each do |path, line| message.add_location(path, line) end tag_label = String.new("@#{tag.tag_name}") tag_label << " [#{tag.types.join(', ')}]" if tag.types message.add_comment(tag_label) end
def extract_tag_text(tag)
def extract_tag_text(tag) return if tag.text.nil? return if tag.text.empty? message = register_message(tag.text) tag.object.files.each do |path, line| message.add_location(path, line) end tag_label = String.new("@#{tag.tag_name}") tag_label << " [#{tag.types.join(', ')}]" if tag.types tag_label << " #{tag.name}" if tag.name message.add_comment(tag_label) end
def generate
-
(String)
- POT format string
def generate pot = String.new(header) sorted_messages = @messages.sort_by do |message| sorted_locations = message.locations.sort sorted_locations.first || [] end sorted_messages.each do |message| generate_message(pot, message) end pot end
def generate_message(pot, message)
def generate_message(pot, message) message.comments.sort.each do |comment| pot << "# #{comment}\n" unless comment.empty? end message.locations.sort.each do |path, line| pot << "#: #{@relative_base_path}/#{path}:#{line}\n" end escaped_message_id = escape_message_id(message.id) escaped_message_id = escaped_message_id.gsub(/\n/, "\\\\n\"\n\"") pot << "msgid \"#{escaped_message_id}\"\n" pot << "msgstr \"\"\n" pot << "\n" pot end
def generate_pot_creation_date_value
def generate_pot_creation_date_value current_time.strftime("%Y-%m-%d %H:%M%z") end
def header
def header <<-EOH DESCRIPTIVE TITLE. right (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER file is distributed under the same license as the PACKAGE package. T AUTHOR <EMAIL@ADDRESS>, YEAR. zy "" "" ct-Id-Version: PACKAGE VERSION\\n" t-Msgid-Bugs-To: \\n" reation-Date: #{generate_pot_creation_date_value}\\n" vision-Date: YEAR-MO-DA HO:MI+ZONE\\n" Translator: FULL NAME <EMAIL@ADDRESS>\\n" age-Team: LANGUAGE <LL@li.org>\\n" age: \\n" Version: 1.0\\n" nt-Type: text/plain; charset=UTF-8\\n" nt-Transfer-Encoding: 8bit\\n" end
def initialize(relative_base_path)
-
relative_base_path
(String
) -- a relative working
def initialize(relative_base_path) @relative_base_path = relative_base_path @extracted_objects = {} @messages = Messages.new end
def parse_files(files)
-
(void)
-
Parameters:
-
files
(Array
) -- a list
def parse_files(files) files.each do |file| extract_paragraphs(file) end end
def parse_objects(objects)
-
(void)
-
Parameters:
-
objects
(Array
) -- a list of
def parse_objects(objects) objects.each do |object| extract_documents(object) end end
def register_message(id)
def register_message(id) @messages.register(id) end