Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "Headers/Localization.h"

#include "Core/Headers/ErrorCodes.h"
#include <SimpleINI/include/SimpleIni.h>

#include "simplefilewatcher/includes/FileWatcher.h"

namespace Divide {
namespace Locale {

namespace {
    CSimpleIni g_languageFile;
    constexpr char* g_languageFileExtension = ".ini";

    /// External modification monitoring system
    std::unique_ptr<FW::FileWatcher> s_LanguageFileWatcher = nullptr;

    class UpdateListener : public FW::FileWatchListener
    {
    public:
        UpdateListener()
        {
        }

        void handleFileAction(FW::WatchID watchid, const FW::String& dir, const FW::String& filename, FW::Action action)
        {
            switch (action)
            {
            case FW::Actions::Add: break;
            case FW::Actions::Delete: break;
            case FW::Actions::Modified:
                detail::onLanguageFileModify(filename.c_str());
                break;

            default:
                DIVIDE_UNEXPECTED_CALL("Unknown file event!");
            }
        };
    } s_fileWatcherListener;
};

namespace detail {
    void onLanguageFileModify(const char* languageFile) {
        // If we modify our currently active language, reinit the Locale system
        if (strcmp((s_localeFile + g_languageFileExtension).c_str(), languageFile) == 0) {
            changeLanguage(s_localeFile);
        }
    }
};

ErrorCode init(const stringImpl& newLanguage) {
    clear();
    if (!s_LanguageFileWatcher) {
         s_LanguageFileWatcher.reset(new FW::FileWatcher());
         s_LanguageFileWatcher->addWatch(Paths::g_LocalisationPath.c_str(), &s_fileWatcherListener);
    }

    detail::s_localeFile = newLanguage;
    // Use SimpleIni library for cross-platform INI parsing
    g_languageFile.SetUnicode();
    g_languageFile.SetMultiLine(true);

    stringImpl file = Paths::g_LocalisationPath + detail::s_localeFile + g_languageFileExtension;

    if (g_languageFile.LoadFile(file.c_str()) != SI_OK) {
        return ErrorCode::NO_LANGUAGE_INI;
    }

    // Load all key-value pairs for the "language" section
    const CSimpleIni::TKeyVal* keyValue = g_languageFile.GetSection("language");

    assert(keyValue != nullptr &&
           "Locale::init error: No 'language' section found");
    // And add all pairs to the language table
    CSimpleIni::TKeyVal::const_iterator keyValuePairIt = keyValue->begin();
    for (; keyValuePairIt != keyValue->end(); ++keyValuePairIt) {
        stringImpl value(keyValuePairIt->second);
        
        hashAlg::emplace(detail::s_languageTable,
                         _ID_RT(keyValuePairIt->first.pItem),
                         value);
    }

    detail::s_initialized = true;
    return ErrorCode::NO_ERR;
}

void clear() {
    detail::s_languageTable.clear();
    g_languageFile.Reset();
    detail::s_initialized = false;
}

void idle() {
    if (s_LanguageFileWatcher) {
        s_LanguageFileWatcher->update();
    }
}

/// Altough the language can be set at compile time, in-game options may support
/// language changes
void changeLanguage(const stringImpl& newLanguage) {
    /// Set the new language code
    init(newLanguage);

    for (const DELEGATE_CBK<void, const char* /*new language*/>& languageChangeCbk : detail::s_languageChangeCallbacks) {
        languageChangeCbk(newLanguage.c_str());
    }
}

const char* get(U64 key, const char* defaultValue) {
    if (detail::s_initialized) {
        typedef hashMapImpl<U64, stringImpl>::const_iterator citer;
        // When we ask for a string for the given key, we check our language cache first
        citer entry = detail::s_languageTable.find(key);
        if (entry != std::cend(detail::s_languageTable)) {
            // Usually, the entire language table is loaded.
            return entry->second.c_str();
        }
        DIVIDE_UNEXPECTED_CALL("Locale error: INVALID STRING KEY!");
    }

    return defaultValue;
}

const char* get(U64 key) {
    return get(key, "key not found");
}

void addChangeLanguageCallback(const DELEGATE_CBK<void, const char* /*new language*/>& cbk) {
    detail::s_languageChangeCallbacks.emplace_back(cbk);
}

};  // namespace Locale
};  // namespace Divide

Commits for Divide-Framework/trunk/Source Code/Utility/Localization.cpp

Diff revisions: vs.
Revision Author Commited Message
842 Diff Diff IonutCava picture IonutCava Wed 01 Feb, 2017 17:25:15 +0000

[IonutCava]
- Start to implement scripting support via ChaiScript: http://chaiscript.com/
- Cleanup DELEGATE_CBK alias

841 Diff Diff IonutCava picture IonutCava Wed 01 Feb, 2017 14:47:57 +0000

[IonutCava]
- Add callbacks to Localization so that listeners can be informed of language changes
— First callback added to GUIInterface

840 Diff Diff IonutCava picture IonutCava Wed 01 Feb, 2017 14:06:06 +0000

[IonutCava]
- Fix a bug with hot shader reloading and atom file caching
- Add hot language file reloading.
— Changes made to the current language file will be immediately applied

835 Diff Diff IonutCava picture IonutCava Fri 27 Jan, 2017 14:58:07 +0000

[IonutCava]
- Split Engine lib into Core and Engine lib.
- Fix Server build issues

832 Diff Diff IonutCava picture IonutCava Thu 26 Jan, 2017 17:23:11 +0000

[IonutCava]
- More path related work
- Initial code to centralize file I/O (does not compile yet)

795 Diff Diff IonutCava picture IonutCava Wed 23 Nov, 2016 17:14:33 +0000

[IonutCava]
- Remove ULL. Use U64 instead
- Various small bug fixes and typos.

727 Diff Diff IonutCava picture IonutCava Tue 14 Jun, 2016 16:01:38 +0000

[IonutCava]
- Remove node and cmd buffers from GFXDevice and add them as a new BufferData struct to RenderPass class.
— Each render pass holds its own buffers
- Improvements / fixes to the CSM code
- Added a global toggle to enable/disable custom memory allocators

694 Diff Diff IonutCava picture IonutCava Fri 29 Apr, 2016 16:11:44 +0000

[IonutCava]
- More profile timers!
- Allow multiline localised text
- Allow font size specification for GUI.addText call

679 Diff Diff IonutCava picture IonutCava Wed 13 Apr, 2016 21:21:51 +0000

[IonutCava]
- Add unit tests for task system
- Adapt task system for better modularity
- Split Divide-Game into Game lib and Game executable projects
- Cleanup unit test projects

670 IonutCava picture IonutCava Wed 06 Apr, 2016 16:21:35 +0000

[IonutCava]
- getInstance() renamed to instance() for simplicity (should really go away altogether, but that’s a different issue)
- some particle emitter threading updates