f41b982009-05-07Martin Stjernholm // This is a roxen module. Copyright © 2000 - 2009, Roxen IS.
df08942000-01-12Martin Nilsson //
d090922000-03-09Martin Nilsson 
8be6db2000-04-24Martin Nilsson //#pragma strict_types
8546f92000-03-10Martin Nilsson #include <module.h>
df08942000-01-12Martin Nilsson inherit "module";
0917d32013-03-04Anders Johansson constant cvs_version = "$Id$";
df08942000-01-12Martin Nilsson constant thread_safe = 1;
b3281f2000-09-10Martin Nilsson constant module_type = MODULE_URL | MODULE_TAG;
df08942000-01-12Martin Nilsson constant module_name = "Language module II"; constant module_doc = "Handles documents in different languages. "
b286602000-04-24Martin Nilsson  "What language a file is in is specified with the " "language code before the extension. index.sv.html would be a file in swedish " "while index.en.html would be one in english. ";
df08942000-01-12Martin Nilsson 
d090922000-03-09Martin Nilsson void create() {
df08942000-01-12Martin Nilsson  defvar( "default_language", "en", "Default language", TYPE_STRING, "The default language for this server. Is used when trying to "
09958a2001-10-01Martin Nilsson  "decide which language to send when the user hasn't selected any." );
df08942000-01-12Martin Nilsson  defvar( "languages", ({"en","de","sv"}), "Languages", TYPE_STRING_LIST, "The languages supported by this site." ); }
d090922000-03-09Martin Nilsson string default_language;
8be6db2000-04-24Martin Nilsson array(string) languages;
8546f92000-03-10Martin Nilsson string cache_id;
d5ed802001-09-26Martin Nilsson array(string) roxen_languages;
df08942000-01-12Martin Nilsson 
8546f92000-03-10Martin Nilsson void start(int n, Configuration c) {
f171492000-09-14Martin Nilsson  if(c->enabled_modules["content_editor#0"]) { call_out( c->disable_module, 0.5, "language2#0" ); report_error("Language II is not compatible with SiteBuilder content editor.\n"); return; }
225c9b2001-08-28Henrik Grubbström (Grubba)  default_language = lower_case([string]query("default_language")); languages = map([array(string)]query("languages"), lower_case);
d5ed802001-09-26Martin Nilsson  cache_id = "lang_mod"+c->get_config_id(); mapping conv = Standards.ISO639_2.list_639_1(); conv = mkmapping( values(conv), indices(conv) ); roxen_languages = roxen->list_languages() + map(roxen->list_languages(), lambda(string in) { return conv[in]; }); roxen_languages -= ({ 0 });
d090922000-03-09Martin Nilsson }
df08942000-01-12Martin Nilsson 
d090922000-03-09Martin Nilsson // ------------- Find the best language file -------------
df08942000-01-12Martin Nilsson 
d090922000-03-09Martin Nilsson object remap_url(RequestID id, string url) {
58cb512003-05-13Jonas Wallden  if (!languages) return 0; // module not initialized
d090922000-03-09Martin Nilsson  if(!id->misc->language_remap) id->misc->language_remap=([]); if(id->misc->language_remap[url]==1) return 0; id->misc->language_remap[url]++;
df08942000-01-12Martin Nilsson  if(id->conf->stat_file(url, id)) return 0;
d090922000-03-09Martin Nilsson  // find files multiset(string) found; mapping(string:string) files;
8be6db2000-04-24Martin Nilsson  array split=[array]cache_lookup(cache_id,url); if(!split) {
d090922000-03-09Martin Nilsson  found=(<>); files=([]); split=url/"/"; string path=split[..sizeof(split)-2]*"/"+"/", file=split[-1]; id->misc->language_remap[path]=1; array realdir=id->conf->find_dir(path, id); if(!realdir) return 0; multiset dir=aggregate_multiset(@realdir); split=file/"."; if(!sizeof(split)) split=({""}); file=split[..sizeof(split)-2]*"."; string this; foreach(languages, string lang) { string this=file+"."+lang+"."+split[-1]; if(dir[this]) { found+=(<lang>); files+=([lang:path+this]); } }
8546f92000-03-10Martin Nilsson  cache_set(cache_id, url, ({ found,files }) );
d090922000-03-09Martin Nilsson  } else [found,files]=split;
14ca442009-02-19Jonas Wallden  // Register known languages with the protocol cache PrefLanguages pl = id->misc->pref_languages; if (pl) pl->register_known_language_forks(found, id); // Get language search order array(string) find_lang = (pl ? pl->get_languages() : ({ }) ) + ({ default_language }); find_lang &= languages; // Remap foreach(find_lang, string lang) {
df08942000-01-12Martin Nilsson  if(found[lang]) {
8be6db2000-04-24Martin Nilsson  url=Roxen.fix_relative(url, id);
df08942000-01-12Martin Nilsson  string type=id->conf->type_from_filename(url);
d090922000-03-09Martin Nilsson  if(!id->misc->defines) id->misc->defines=([]); id->misc->defines->language=lang;
8546f92000-03-10Martin Nilsson  id->misc->defines->present_languages=found;
d090922000-03-09Martin Nilsson  id->not_query=files[lang]; id->misc->language_remap=([]); return id; }
df08942000-01-12Martin Nilsson  } return 0; }
d090922000-03-09Martin Nilsson  // ---------------- Tag definitions --------------
8be6db2000-04-24Martin Nilsson function(string:string) translator(array(string) client, RequestID id) {
d5ed802001-09-26Martin Nilsson  client= ({ id->misc->defines->language }) + client + ({ default_language });
d090922000-03-09Martin Nilsson  foreach(client, string lang)
d5ed802001-09-26Martin Nilsson  if(has_value(roxen_languages,lang)) {
d090922000-03-09Martin Nilsson  return roxen->language_low(lang)->language; }
d5ed802001-09-26Martin Nilsson  return roxen->language_low("en")->language;
df08942000-01-12Martin Nilsson }
d090922000-03-09Martin Nilsson class TagLanguage { inherit RXML.Tag; constant name = "language";
1b2d742001-10-08Anders Johansson  constant flags = RXML.FLAG_EMPTY_ELEMENT;
d090922000-03-09Martin Nilsson  class Frame { inherit RXML.Frame; array do_return(RequestID id) {
8be6db2000-04-24Martin Nilsson  string lang=([mapping(string:mixed)]id->misc->defines)->language;
8546f92000-03-10Martin Nilsson  if(args->type=="code") {
d090922000-03-09Martin Nilsson  result=lang; return 0; } result=translator( ({}),id )(lang); return 0; } }
df08942000-01-12Martin Nilsson }
d090922000-03-09Martin Nilsson class TagUnavailableLanguage { inherit RXML.Tag; constant name = "unavailable-language";
1b2d742001-10-08Anders Johansson  constant flags = RXML.FLAG_EMPTY_ELEMENT;
df08942000-01-12Martin Nilsson 
d090922000-03-09Martin Nilsson  class Frame { inherit RXML.Frame;
df08942000-01-12Martin Nilsson 
d090922000-03-09Martin Nilsson  array do_return(RequestID id) {
8546f92000-03-10Martin Nilsson  string lang=id->misc->pref_languages->get_languages()[0];
8be6db2000-04-24Martin Nilsson  if(lang==([mapping(string:mixed)]id->misc->defines)->language) return 0;
8546f92000-03-10Martin Nilsson  if(args->type=="code") {
d090922000-03-09Martin Nilsson  result=lang; return 0; } result=translator( ({}),id )(lang); return 0; } } }
df08942000-01-12Martin Nilsson 
8546f92000-03-10Martin Nilsson TAGDOCUMENTATION; #ifdef manual constant tagdoc=([
0a15f42001-10-09Johan Sundström  "language":"<desc type='tag'><p><short>Show the pages language.</short></p></desc>", "unavailable-language":"<desc type='cont'><p><short>Show what language the user " "wanted, if this isn't it.</short></p></desc>"
8546f92000-03-10Martin Nilsson ]); #endif