/**
 * File:	modules/Language.ycp
 * Module:	Language
 * Summary:	This module does all language related stuff:
 * Authors:	Klaus Kaempf <kkaempf@suse.de>
 *		Thomas Roelz <tom@suse.de>
 *
 * $Id: Language.ycp 22532 2005-03-14 15:39:31Z jsuchome $
 */

{

module "Language";
textdomain "country";


import "AsciiFile";
import "Encoding";
import "Misc";
import "Mode";
import "ProductFeatures";
import "Stage";


/**
 * currently selected language
 */
global string language = "en_US";


/**
 * user readable description of language
 */
string name = "English (US)";

boolean linuxrc_language_set = false;

/**
 * Default language to be restored with MakeProposal.
 */
string default_language = "en_US";


/**
 * Default settings for ROOT_USES_LANG in /etc/sysconfig/language
 */
string rootlang = "ctype";


/**
 * Default settings for INSTALLED_LANGUAGES in /etc/sysconfig/language
 */
global string languages	= "";

/**
 * Use utf8 in locale
 */
boolean use_utf8 = true;

/**
 * ncurses mode
 */
boolean text_mode	= nil;

global boolean ExpertSettingsChanged = false;

/**
 * level of translation completeness
 */
map<string,integer> translation_status	= $[];


/**
 * return the value of text_mode (true for ncurses)
 */
global define boolean GetTextMode () {

    if (text_mode== nil)
    {
	map display_info	= UI::GetDisplayInfo ();
	text_mode		= display_info["TextMode"]:false;
    }
    return text_mode;
}

/**
 * Get the language DB
 * @return Language DB
 */
define map<string, list> get_languages_map() {

    map<string, list> languages_map = (map<string, list>)
	WFM::CallFunction ("languages", []);

    if ( languages_map == nil ) languages_map = $[];

    return( languages_map );
}

/**
 * Set module to selected language.
 * @param lang language string ISO code of language
 */
global define void Set (string lang) {

    y2milestone( "lang:%1", lang );

    if (language != lang)	// Do it only if different
    {
	map<string, list> languages_map = get_languages_map();

	if (!haskey (languages_map, lang) && size(lang) > 0)
	{
	    lang = substring (lang, 0, 2);
	    boolean found = false;
	    foreach (string k, list dummy, languages_map,
	    {
		if (!found && substring (k, 0, 2) ==lang)
		{
		    found = true;
		    lang = k;
		}
	    });
	}
	name		= languages_map[lang, 0]:"English";
	language	= lang;
	Encoding::SetEncLang (language);
    }

    if (Stage::initial () && !Mode::test ())
    {
	map yinf = $[];
	AsciiFile::SetDelimiter (yinf, " ");
	AsciiFile::ReadFile (yinf, "/etc/yast.inf");
	list lines = AsciiFile::FindLineField (yinf, 0, "Language:");
	if (size(lines) > 0)
	{
	    AsciiFile::ChangeLineField (yinf, lines[0]:-1, 1, language);
	}
	else
	{
	    AsciiFile::AppendLine (yinf, ["Language:", language] );
	}
	AsciiFile::RewriteFile (yinf, "/etc/yast.inf");

	if (!GetTextMode ())
	{
	    SCR::Write (.FvwmCommand.lang, language);
	}
    }
}

global define boolean LinuxrcLangSet() {

    return linuxrc_language_set;
}

global define string GetLocaleString (string lang) {

    map<string, list> languages_map = get_languages_map();
    list language_info = languages_map[lang]:[];

    // full language code
    string val = language;
    if( use_utf8 )
	{
	val = val + language_info[2]:"";
	}
    else
	{
	val = val + language_info[3]:"";
	}
    y2milestone( "locale %1", val );
    return val;
    }


/**
 * Store current language as default language.
 */
global define void SetDefault() {
    y2milestone("Setting default language: %1", language);
    default_language = language;
    return;
}

/**
 * Get the map for conversion of old lang codes to new ISO-codes
 * (since Rel. 8.0)
 *
 * @return conversion map
 */
define map get_lang2iso() ``{

    // The old_lang --> ISO conversion map.
    //
    map lang2iso = (map)SCR::Read( .target.yast2, "lang2iso.ycp");

    if ( lang2iso == nil ) lang2iso = $[];

    return( lang2iso );
}


/**
 * Constructor
 *
 * Initializes module either from /etc/install.inf
 * or from /etc/sysconfig/language
 */
global define void Language() {

    if (Stage::initial ())
    {
	string lang = (string)SCR::Read (.content.LANGUAGE);
	y2milestone ("content LANGUAGE %1", lang);
	if (SCR::Read (.target.size, "/etc/install.inf") > 0)
	{
	    string tmp_l = (string)SCR::Read (.etc.install_inf.Locale);
	    y2milestone ("install_inf Locale %1", tmp_l);
	    if (tmp_l!=nil && size(tmp_l)>0)
	    {
		lang = tmp_l;
		if( lang != "en_US" )
		{
		    linuxrc_language_set = true;
		}
	    }
	}
	if (lang == nil)
	    lang = "";
	y2milestone( "lang from /etc/install.inf: %1", lang );
	if (lang == "")
	{
	    lang = Pkg::GetLocale();
	    y2milestone ("setting lang to default language: %1", lang);
	}
        // Ignore any previous settings and take language from control file.
        if (ProductFeatures::language != "")
        {
            lang = ProductFeatures::language;
	    y2milestone ("setting lang to ProductFeatures::language: %1", lang);
        }
	Set (lang);		// coming from /etc/install.inf
	SetDefault ();		// also default
    }
    else
    {
	string local_lang =
	    Misc::SysconfigRead (.sysconfig.language.RC_LANG, "");
	y2milestone( "reading RC_LANG %1", local_lang );
	if (size (local_lang) == 0)
	{
	    // Try to read the old YaST1 language and convert setting.
	    string y1lang =
		Misc::SysconfigRead (.sysconfig.language.DEFAULT_LANGUAGE, "");
	    map lang2iso = get_lang2iso();
	    if (size (y1lang)>0 && size (lang2iso[y1lang]:"") > 0)
	    {
		local_lang = lang2iso[y1lang]:"";
	    }
	}
	if (size(local_lang) == 0)
	{
	    local_lang = language;
	}

	integer pos = findfirstof (local_lang, ".@");

	if (pos != nil && pos >= 0)
	{
	    local_lang = substring( local_lang, 0, pos );
	}

	y2milestone( "setting language to %1", local_lang );

	Set (local_lang);
	SetDefault();		// also default
    }
    if (SCR::Read (.target.size, "/etc/sysconfig/language") > 0)
    {
	rootlang =
	    Misc::SysconfigRead (.sysconfig.language.ROOT_USES_LANG, rootlang);
	if (!Stage::initial ())
	{
	    string val = toupper (
		Misc::SysconfigRead (.sysconfig.language.RC_LANG, ""));
	    use_utf8 = find (val, ".UTF-8") > 0;
	}
	else
	{
	    use_utf8 = true;
	}
	languages =
	    Misc::SysconfigRead (.sysconfig.language.INSTALLED_LANGUAGES, "");
    }
    Encoding::SetUtf8Lang (use_utf8);
}

/**
 * GetExpertValues()
 *
 * Return the values for the various expert settings in a map
 *
 * @param       -
 *
 * @return  map with values filled in
 *
 */
global define map GetExpertValues () {

    return $[
	"rootlang"  : rootlang,
        "use_utf8"  : use_utf8
    ];
}

/**
 * SetExpertValues()
 *
 * Set the values of the various expert setting
 *
 * @param       val     map with new values of expert settings
 *
 * @return  void
 *
 */
global define void SetExpertValues (map val) {

    if (haskey (val,"rootlang") && size (val["rootlang"]:"") >0)
    {
        rootlang = val["rootlang"]:"";
    }
    if (haskey (val,"use_utf8"))
    {
        use_utf8 = val["use_utf8"]:false;
	Encoding::SetUtf8Lang (use_utf8);
    }
}


/**
 * WfmSetLanguag()
 *
 * Set the current language in WFM and UI
 *
 * @param       -
 *
 * @return      -
 */
global define void WfmSetLanguage () {

    string encoding	= (use_utf8) ? "UTF-8" : Encoding::console;

    y2milestone( "language %1 enc %2 utf8:%3", language, encoding, use_utf8 );

    UI::SetLanguage (language, encoding);

    if (use_utf8)
    {
	WFM::SetLanguage(language, "UTF-8");
    }
    else
    {
	WFM::SetLanguage(language);
    }
}


/**
 * Return proposal string.
 *
 * @return	string	user readable description.
 *		If force_reset is true reset the module to the language
 *		stored in default_language.
 */
global define list<string> MakeProposal (boolean force_reset,boolean language_changed)
{
    y2milestone("force_reset: %1", force_reset);
    y2milestone("language_changed: %1", language_changed);

    if (force_reset)
    {
	Set (default_language);	// reset
    }
    list<string> ret =  [
	// summary label
	sformat (_("Primary Language: %1"), name)
    ];
    if (languages != "" && languages != language)
    {
	list<string> langs	= [];
	map<string, list> languages_map = get_languages_map();
	foreach (string lang, splitstring (languages, ","), {
	    if (lang != language)
	    {
		string l = languages_map[lang,4]:languages_map[lang,0]:"";
		if (l != "")
		    langs = add (langs, l);
	    }
	});
	if (size (langs) > 0)
	{
	    // summary label
	    ret = add (ret, sformat (_("Additional Languages: %1"),
		mergestring (langs,", ")));
	}
    }
    return ret;
}

/**
 * return user readable description of language
 */
global define string GetName () {

    return name;
}

/**
 * Return a map of ids and names to build up a selection list
 * for the user. The key is used later in the Set function
 * to select this language. The name is a translated string.
 *
 * @return map of $[ language : [ utf8-name, ascii-name] ...]
 *			for all known languages
 *			'language' is the (2 or 5 char)  ISO language code.
 *			'utf8-name' is a user-readable (UTF-8 encoded !) string.
 *			'ascii-name' is an english (ascii encoded !) string.
 * @see Set
 */
global define map<string, list> Selection() {

    map<string, list> languages_map = get_languages_map();

    return mapmap (string code, list data, languages_map,
	``($[code: [data[0]:"", data[1]:"", data[4]:data[0]:""]]));
}


/**
 * Save state to target.
 */
global define void Save() {

    string loc = GetLocaleString (language);

    SCR::Write (.sysconfig.language.RC_LANG, loc);

    if (find (loc, "zh_HK") == 0)
    {
	SCR::Write(.sysconfig.language.RC_LC_MESSAGES,"zh_TW"+substring(loc,5));
    }
    else
    {
	// FIXME ugly hack: see bug #47711
	string lc_mess = (string)SCR::Read(.sysconfig.language.RC_LC_MESSAGES);
	if (find (lc_mess, "zh_TW") == 0)
	{
	    SCR::Write (.sysconfig.language.RC_LC_MESSAGES, "");
	}
    }

    SCR::Write (.sysconfig.language.ROOT_USES_LANG, rootlang);
    SCR::Write (.sysconfig.language.INSTALLED_LANGUAGES, languages);
    SCR::Write (.sysconfig.language, nil);

    y2milestone("Saved data for language: <%1>", GetLocaleString(language) );
}



/**
 * de_DE@UTF-8 -> "DE"
 * @return country part of language
 */
global define string GetLanguageCountry() {

    string lang = Language::language;
    if (lang == nil || lang == "")
        lang = Language::default_language;
    if (lang != nil && lang != "")
    {
        if (find (lang, "@") != -1)
            lang = splitstring (lang, "@") [0]:"";
    }
    if (lang != nil && lang != "")
    {
        if (find(lang, "_") != -1)
            lang = splitstring (lang, "_") [1]:"";
	else
	    lang = toupper(lang);
    }

    y2debug("language=%1",lang);
    return lang;
}

/**
 * Returns true if translation for given language is not complete
 */
global define boolean IncompleteTranslation (string lang) {

    if (!haskey (translation_status,lang))
    {
	string file	= "/usr/lib/YaST2/trans/" + lang + ".status";
	string ll	= splitstring (lang, "_") [0]:"";
	if (ll != "")
	    file	= "/usr/lib/YaST2/trans/" + ll + ".status";

	string status	= (string) SCR::Read (.target.string, file);

	if ((status == nil || status == "") && ll != "")
	{
	    file	= "/usr/lib/YaST2/trans/" + lang + ".status";
	    status	= (string) SCR::Read (.target.string, file);
	}
	if (status != nil && status != "")
	    translation_status[lang]	= tointeger (status);
	else
	    translation_status[lang]	= 100;
    }
    integer treshold =
	tointeger (ProductFeatures::incomplete_translation_treshold);
    if (treshold == nil) treshold = 95;

    return translation_status[lang]:0 < treshold;
}

/* EOF */
}
