#!/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 # 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)