1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
|
#!/usr/bin/env ruby
# frozen_string_literal: true
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
# SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
# Generates timezone tables out of tzdata.zi backing data such that the pretty names may be translated.
require 'erb'
require 'ostruct'
# Wraps template rendering. Templating is implemented using the ERB template system.
class Template
def self.render(context)
erb = ERB.new(File.read("#{__dir__}/timezonesi18n_generated.h.erb"))
erb.result(context.instance_eval { binding })
end
end
# Context object for template rendering. Inside the template file anything defined in here may be used.
# For simplicity's sake continents and cities are not modeled as fully functional objects but rather use
# this context wrapper. Slightly less code.
class RenderContext < OpenStruct
def initialize(continents:)
super
end
def continent_description(_continent)
'This is a continent/area associated with a particular timezone'
end
# prettify continent name
def to_contient_name(continent)
continent # leave unchanged, they are all lovely
end
end
raise 'tzdata.zi missing, your tzdata was possibly built without' unless File.exist?('/usr/share/zoneinfo/tzdata.zi')
data = File.read('/usr/share/zoneinfo/tzdata.zi')
continents = []
data.split("\n").each do |line|
line = line.strip
next if line[0] == '#' # comment
# zi files have a tricky format. only look at lines that make sense for us (Zone entries and Link entries)
is_zone = line[0].downcase == 'z'
is_link = line[0].downcase == 'l'
next unless is_zone || is_link
line_parts = line.split(' ')
# Since we have 2 line formats, the location of the timezone is different in each
tz = is_zone ? line_parts[1] : line_parts[2]
parts = tz.split('/')
# some links are fishy single names we can't use (e.g. `L Europe/Warsaw Poland`)
next if parts.size < 2
continent = parts[0]
# some links also have fake continent values (e.g. `L America/Denver SystemV/MST7MDT`) followed by regions therein
next if %w[systemv us etc canada brazil mexico chile].any? { |x| x == continent.downcase }
continents << continent
end
continents = continents.sort_by(&:downcase).uniq
data = Template.render(RenderContext.new(continents: continents))
File.write("#{__dir__}/timezonesi18n_generated.h", data)
|