Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svtools/source/misc/langhelp.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 */
9
10
#include <sal/config.h>
11
12
#include <string_view>
13
14
#include <comphelper/sequence.hxx>
15
#include <i18nlangtag/languagetag.hxx>
16
#include <i18nlangtag/mslangid.hxx>
17
#include <officecfg/Office/Common.hxx>
18
#include <officecfg/System.hxx>
19
#include <o3tl/string_view.hxx>
20
#include <org/freedesktop/PackageKit/SyncDbusSessionHelper.hpp>
21
#include <rtl/ustring.hxx>
22
#include <svtools/langhelp.hxx>
23
#include <comphelper/diagnose_ex.hxx>
24
#include <vcl/idle.hxx>
25
#include <vcl/svapp.hxx>
26
#include <vcl/settings.hxx>
27
#include <config_langs.h>
28
#include <config_vendor.h>
29
30
void localizeWebserviceURI( OUString& rURI )
31
0
{
32
0
    OUString aLang = Application::GetSettings().GetUILanguageTag().getLanguage();
33
0
    if ( aLang.equalsIgnoreAsciiCase("pt")
34
0
         && Application::GetSettings().GetUILanguageTag().getCountry().equalsIgnoreAsciiCase("br") )
35
0
    {
36
0
        aLang = "pt-br";
37
0
    }
38
0
    if ( aLang.equalsIgnoreAsciiCase("zh") )
39
0
    {
40
0
        if ( Application::GetSettings().GetUILanguageTag().getCountry().equalsIgnoreAsciiCase("cn") )
41
0
            aLang = "zh-cn";
42
0
        if ( Application::GetSettings().GetUILanguageTag().getCountry().equalsIgnoreAsciiCase("tw") )
43
0
            aLang = "zh-tw";
44
0
    }
45
46
0
    rURI += aLang;
47
0
}
48
49
OUString getInstalledLocaleForLanguage(css::uno::Sequence<OUString> const & installed, OUString const & locale)
50
0
{
51
0
    if (locale.isEmpty())
52
0
        return OUString();  // do not attempt to resolve anything
53
54
0
    if (comphelper::findValue(installed, locale) != -1)
55
0
        return locale;
56
57
0
    std::vector<OUString> fallbacks(LanguageTag(locale).getFallbackStrings(false));
58
0
    auto pf = std::find_if(fallbacks.begin(), fallbacks.end(),
59
0
        [&installed](const OUString& rf) { return comphelper::findValue(installed, rf) != -1; });
60
0
    if (pf != fallbacks.end())
61
0
        return *pf;
62
0
    return OUString();
63
0
}
64
65
static std::unique_ptr<Idle> xLangpackInstaller;
66
67
namespace {
68
69
class InstallLangpack : public Idle
70
{
71
    std::vector<OUString> m_aPackages;
72
public:
73
    explicit InstallLangpack(std::vector<OUString>&& rPackages)
74
0
        : Idle("install langpack")
75
0
        , m_aPackages(std::move(rPackages))
76
0
    {
77
0
        SetPriority(TaskPriority::LOWEST);
78
0
    }
79
80
    virtual void Invoke() override
81
0
    {
82
0
        vcl::Window* pTopWindow = Application::GetActiveTopWindow();
83
0
        if (!pTopWindow)
84
0
            pTopWindow = Application::GetFirstTopLevelWindow();
85
0
        if (!pTopWindow)
86
0
        {
87
0
            Start();
88
0
            return;
89
0
        }
90
0
        try
91
0
        {
92
0
            using namespace org::freedesktop::PackageKit;
93
0
            css::uno::Reference<XSyncDbusSessionHelper> xSyncDbusSessionHelper(SyncDbusSessionHelper::create(comphelper::getProcessComponentContext()));
94
0
            xSyncDbusSessionHelper->InstallPackageNames(comphelper::containerToSequence(m_aPackages), OUString());
95
0
        }
96
0
        catch (const css::uno::Exception&)
97
0
        {
98
0
            TOOLS_INFO_EXCEPTION("svl", "trying to install a LibreOffice langpack");
99
0
        }
100
0
        xLangpackInstaller.reset();
101
0
    }
102
};
103
104
}
105
106
OUString getInstalledLocaleForSystemUILanguage(const css::uno::Sequence<OUString>& rLocaleElementNames, bool bRequestInstallIfMissing, const OUString& rPreferredLocale)
107
0
{
108
0
    OUString wantedLocale(rPreferredLocale);
109
0
    if (wantedLocale.isEmpty())
110
0
        wantedLocale = officecfg::System::L10N::UILocale::get();
111
112
0
    OUString locale = getInstalledLocaleForLanguage(rLocaleElementNames, wantedLocale);
113
0
    if (bRequestInstallIfMissing && locale.isEmpty() && !wantedLocale.isEmpty() && !Application::IsHeadlessModeEnabled() &&
114
0
        officecfg::Office::Common::PackageKit::EnableLangpackInstallation::get())
115
0
    {
116
0
        LanguageTag aWantedTag(wantedLocale);
117
0
        if (aWantedTag.getLanguage() != "en")
118
0
        {
119
            // Get the list of langpacks that this build was configured to include
120
0
            std::vector<OUString> aPackages;
121
0
            static constexpr std::u16string_view sAvailableLocales(u"" WITH_LANG);
122
0
            std::vector<OUString> aAvailable;
123
0
            sal_Int32 nIndex = 0;
124
0
            do
125
0
            {
126
0
                aAvailable.emplace_back(o3tl::getToken(sAvailableLocales, 0, ' ', nIndex));
127
0
            }
128
0
            while (nIndex >= 0);
129
            // See which one matches the desired ui locale
130
0
            OUString install = getInstalledLocaleForLanguage(comphelper::containerToSequence(aAvailable), wantedLocale);
131
0
            if (!install.isEmpty() && install != "en-US")
132
0
            {
133
0
                std::string_view sVendor(OOO_VENDOR);
134
0
                if (sVendor == "Red Hat, Inc." || sVendor == "The Fedora Project")
135
0
                {
136
                    // langpack is the typical Fedora/RHEL naming convention
137
0
                    LanguageType eType = aWantedTag.getLanguageType();
138
0
                    if (MsLangId::isSimplifiedChinese(eType))
139
0
                        aPackages.emplace_back("libreoffice-langpack-zh-Hans");
140
0
                    else if (MsLangId::isTraditionalChinese(eType))
141
0
                        aPackages.emplace_back("libreoffice-langpack-zh-Hant");
142
0
                    else if (install == "pt")
143
0
                        aPackages.emplace_back("libreoffice-langpack-pt-PT");
144
0
                    else
145
0
                        aPackages.emplace_back("libreoffice-langpack-" + install);
146
0
                }
147
0
                else if (sVendor == "The Document Foundation/Debian" || sVendor == "The Document Foundation, Debian and Ubuntu")
148
0
                {
149
                    // l10n is the typical Debian/Ubuntu naming convention
150
0
                    aPackages.emplace_back("libreoffice-l10n-" + install);
151
0
                }
152
0
            }
153
0
            if (!aPackages.empty())
154
0
            {
155
0
                xLangpackInstaller.reset(new InstallLangpack(std::move(aPackages)));
156
0
                xLangpackInstaller->Start();
157
0
            }
158
0
        }
159
0
    }
160
0
    if (locale.isEmpty())
161
0
        locale = getInstalledLocaleForLanguage(rLocaleElementNames, u"en-US"_ustr);
162
0
    if (locale.isEmpty() && rLocaleElementNames.hasElements())
163
0
        locale = rLocaleElementNames[0];
164
0
    return locale;
165
0
}
166
167
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */