C++ how to multilanguage?
I found this old topic:
viewtopic.php?f=3&t=54&hilit=multi+language
there is some example from sfernandez, it is still relevant for Noesis 2.0.2?
If yes, how can I load this language.xaml file and use it? I want dynamicaly change the language for my program.
viewtopic.php?f=3&t=54&hilit=multi+language
there is some example from sfernandez, it is still relevant for Noesis 2.0.2?
If yes, how can I load this language.xaml file and use it? I want dynamicaly change the language for my program.
-
sfernandez
Site Admin
- Posts: 3005
- Joined:
Re: C++ how to multilanguage?
You can take a look at NGUI Examples from showcase section: viewtopic.php?f=12&t=485
Specifically at Example 10 - Localization.
It shows one way to organize your language dictionaries, how to expose them in your viewmodel, and how to bind text values from the UI.
Specifically at Example 10 - Localization.
It shows one way to organize your language dictionaries, how to expose them in your viewmodel, and how to bind text values from the UI.
Re: C++ how to multilanguage?
Thanks, but I am not sure what is the best and safe way where to add dataContext.
Before you give me example I discover myself this:And it is working when I binding some text from my lang.xaml
for change language, it will be safe to change m_ResourceDirctionary->SetSource("Lang/langENG.xaml") ? Or this->SetDataContext(someLangObject) for MainGrid is better?
The last question, where can I set sources or dataContext when I use multiple windows? I use allways MainGrid class as base for all windows (and it working), but I am not sure if it good idea.
Before you give me example I discover myself this:
Code: Select all
MainGrid::MainGrid()
{
m_ResourceDirctionary = *new Noesis::ResourceDictionary;
m_ResourceDirctionary->SetSource("Lang/langSVK.xaml");
this->SetResources(m_ResourceDirctionary.GetPtr());
}
for change language, it will be safe to change m_ResourceDirctionary->SetSource("Lang/langENG.xaml") ? Or this->SetDataContext(someLangObject) for MainGrid is better?
The last question, where can I set sources or dataContext when I use multiple windows? I use allways MainGrid class as base for all windows (and it working), but I am not sure if it good idea.
Re: C++ how to multilanguage?
I am not able to recreate example in to C++. But I did something similar and instead DataContext I use Resource. When I select another language, resource is changed. It is working but UI not refresh the text. Only in another windows (not in main) if is reopen.
If I use DataContext, then text is changed, but it is working only for main window. Inside another window, text is not shown. I think because DataContext is not set properly, but I use MainGrid for the all windows.
Here is xaml
MainGrid:
New View for Options Window
GridView for Options (ContainerItemOtions )
If I use DataContext, then text is changed, but it is working only for main window. Inside another window, text is not shown. I think because DataContext is not set properly, but I use MainGrid for the all windows.
Here is xaml
MainGrid:
Code: Select all
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Name="MainGrid" x:Class="MainGrid" >
// .. code
<Grid.Resources>
<DataModel x:Name="dataModel" />
</Grid.Resources>
// .. code
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" Margin="10 0 10 0" >
<TextBlock Text="{Binding Language[rd_button_Nastavenia]}" />
</StackPanel>
</Grid>
Code: Select all
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Name="MainGrid" x:Class="MainGrid" UseLayoutRounding="True" >
// .. code
<ContainerItemOtions Grid.Row="1" />
</Grid>
Code: Select all
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Name="containerItemOtions" x:Class="containerItemOtions" UseLayoutRounding="True" >
<Grid Grid.Row="1" >
<StackPanel Grid.Column="1" >
<GroupBox Header="Nastavenia" >
<Grid >
<StackPanel Orientation="Vertical" Grid.Row="0" >
<RadioButton
Content="{Binding Language[rd_button_Nastavenia]}" // show nothing
Focusable="False" />
</StackPanel>
</Grid>
</GroupBox>
</StackPanel>
</Grid>
</Grid>
Re: C++ how to multilanguage?
Ok, I discover that DataContext is not inherited inside ListBox and other windows. But If I use this:
than I see this text everywhere (inside UserControl or another window) and text is change if I set different language.
Code: Select all
Content="{Binding ElementName=MainGrid, Path=DataContext.Language[rd_button_Nastavenia]}"
-
sfernandez
Site Admin
- Posts: 3005
- Joined:
Re: C++ how to multilanguage?
Hi,
DataContext is usually set on code-behind just after component is initialized:Thanks, but I am not sure what is the best and safe way where to add dataContext.
Code: Select all
MainGrid()
{
InitializeComponent();
Ptr<ViewModel> viewModel = *new ViewModel();
//...
SetDataContext(viewModel.GetPtr());
}
Hope this helps to understand how to translate Localization sample to C++, we tried to be almost the same as in C#:I am not able to recreate example in to C++
Code: Select all
class Language: public BaseComponent
{
public:
Language(const NsChar* n, ResourceDictionary* r): name(n), resources(r) { }
const NsChar* GetName() const { return name.c_str(); }
ResourceDictionary* GetResources() const { return resources.GetPtr(); }
private:
NsString name;
Ptr<ResourceDictionary> resources;
NS_IMPLEMENT_INLINE_REFLECTION(Language, BaseComponent)
{
NsProp("Name", &Language::GetName);
NsProp("Resources", &Language::GetResources);
}
};
Code: Select all
class ViewModel: public BaseComponent, public INotifyPropertyChanged
{
public:
ViewModel(): languages(*new ObservableCollection<Language>())
{
}
// read-only property, only has getter
ObservableCollection<Language>* GetLanguages() const { return languages.GetPtr(); }
// writable property has getter and setter were property changes are notified
Language* GetSelectedLanguage() const { return selectedLanguage.GetPtr(); }
void SetSelectedLanguage(Language* language)
{
if (selectedLanguage != language)
{
selectedLanguage.Reset(language);
OnPropertyChanged("SelectedLanguage");
}
}
// ... other properties follow the same pattern
PropertyChangedEventHandler& PropertyChanged()
{
return propertyChanged;
}
NS_IMPLEMENT_INTERFACE_FIXUP
private:
void OnPropertyChanged(const NsChar* propertyName)
{
if (!propertyChanged.Empty())
{
propertyChanged(this, PropertyChangedEventArgs(NsSymbol(propertyName)));
}
}
private:
Ptr<ObservableCollection<Language>> languages;
Ptr<Language> selectedLanguage;
PropertyChangedEventHandler propertyChanged;
NS_IMPLEMENT_INLINE_REFLECTION(ViewModel, BaseComponent)
{
NsImpl<INotifyPropertyChanged>();
NsProp("Languages", &ViewModel::GetLanguages);
NsProp("SelectedLanguage", &ViewModel::GetSelectedLanguage, &ViewModel::SetSelectedLanguage);
}
};
Code: Select all
class MainGrid: public Grid
{
public:
MainGrid()
{
InitializeComponent();
Ptr<ViewModel> viewModel = *new ViewModel();
Ptr<ResourceDictionary> svk = GUI::LoadXaml<ResourceDictionary>("Lang/langSVK.xaml");
Ptr<Language> langSVK = *new Language("Svenska", svk.GetPtr());
viewModel->GetLanguages()->Add(langSVK.GetPtr());
Ptr<ResourceDictionary> eng = GUI::LoadXaml<ResourceDictionary>("Lang/langENG.xaml");
Ptr<Language> langENG = *new Language("English", eng.GetPtr());
viewModel->GetLanguages()->Add(langENG.GetPtr());
viewModel->SetSelectedLanguage(langENG.GetPtr());
SetDataContext(viewModel.GetPtr());
}
private:
void InitializeComponent()
{
GUI::LoadComponent(this, "MainGrid.xaml");
}
NS_IMPLEMENT_INLINE_REFLECTION(MainGrid, Grid)
{
NsMeta<TypeId>("MainGrid");
}
};
DataContext property is inherited down through the UI tree, but some controls change DataContext on their visual tree. For example, a ContentPresenter will set its Content as DataContext of the data template used to visualize it. All ItemsControl (as ListBox) will assign the item as DataContext of the item container and data template used to visualize the item, etc. So you have to take this into account when defining the bindings in your UI.If I use DataContext, then text is changed, but it is working only for main window. Inside another window, text is not shown. I think because DataContext is not set properly, but I use MainGrid for the all windows.
Ok, I discover that DataContext is not inherited inside ListBox and other windows.
Re: C++ how to multilanguage?
Thank you very much for the code, this is interesting.
I made different solution. Can you please take a look, and make critique about my solution? It is ok?
(My solution search for all files in directory and then add language / languages in to colection. This is for when user decide translate to different language.)
I made different solution. Can you please take a look, and make critique about my solution? It is ok?
(My solution search for all files in directory and then add language / languages in to colection. This is for when user decide translate to different language.)
Code: Select all
NS_DECLARE_SYMBOL(Language);
class LanguageModel :
public Noesis::BaseComponent // BaseComponent ResourceDictionary
, public Noesis::INotifyPropertyChanged
{
public:
LanguageModel();
~LanguageModel();
void mf_SelectLang(unsigned int lang);
Noesis::ResourceDictionary * mf_GetLang() const;
void mf_SetLang(Noesis::ResourceDictionary * lang);
size_t mf_GetSizeOfLang() const;
NsString mf_GetLanguageNames(unsigned int &n) const;
Noesis::PropertyChangedEventHandler& PropertyChanged();
static const Noesis::Gui::DependencyProperty * m_ResourceProperty;
NS_IMPLEMENT_INTERFACE_FIXUP;
private:
fileSystem::path m_path;
std::list<NsString> m_LanguageNameList;
Noesis::Ptr<Noesis::ObservableCollection<Noesis::ResourceDictionary>> m_LangCollectionItems;
Noesis::ResourceDictionary * m_RD;
Noesis::PropertyChangedEventHandler changed;
void Changed(NsSymbol prop);
NS_IMPLEMENT_INLINE_REFLECTION(LanguageModel, Noesis::BaseComponent)
{
NsMeta<Noesis::TypeId>("languageModel");
NsImpl<Noesis::Gui::INotifyPropertyChanged>();
NsProp("Language"
, &LanguageModel::m_RD
);
}
};
Code: Select all
LanguageModel::LanguageModel()
{
m_LangCollectionItems = *new Noesis::ObservableCollection<Noesis::ResourceDictionary>;
fileSystem::path p;
std::string pathString;
m_path.assign("Resources/gui/Lang");
for (fileSystem::directory_entry de : fileSystem::recursive_directory_iterator( m_path , fileSystem::directory_options::none ) )
{
if (!fileSystem::is_directory(de))
{
p = de;
if (p.extension() == ".xaml")
{
pathString = "Lang/" + p.filename().string();
Noesis::Ptr<Noesis::ResourceDictionary> lang = *new Noesis::ResourceDictionary;
lang->SetSource(pathString.c_str());
NsString str = Noesis::ToString(lang->FindName("languageName"));
m_LanguageNameList.insert(m_LanguageNameList.end(), str.c_str()); // for language list inside GUI
m_LangCollectionItems->Add(lang.GetPtr());
pathString.clear();
}
}
}
m_RD = m_LangCollectionItems->Get(0);
}
/// -------------------------------------------------------------------------------------------------------------------
LanguageModel::~LanguageModel()
{
m_LangCollectionItems->Clear();
m_LangCollectionItems.Reset();
m_LanguageNameList.clear();
m_path.clear();
}
// ====================================================================================================================
// most of code here is not finished.
/// -------------------------------------------------------------------------------------------------------------------
void LanguageModel::mf_SelectLang(unsigned int lang)
{
if (lang == 0 || lang == 1)
{
mf_SetLang(m_LangCollectionItems->Get(lang));
}
}
/// -------------------------------------------------------------------------------------------------------------------
Noesis::ResourceDictionary * LanguageModel::mf_GetLang() const { return m_RD; }
/// -------------------------------------------------------------------------------------------------------------------
void LanguageModel::mf_SetLang(Noesis::ResourceDictionary * lang)
{
m_RD = lang;
Changed(NSS(Language)); // SelectedLanguage
}
/// -------------------------------------------------------------------------------------------------------------------
size_t LanguageModel::mf_GetSizeOfLang() const { return m_LangCollectionItems->Count(); }
/// -------------------------------------------------------------------------------------------------------------------
NsString LanguageModel::mf_GetLanguageNames(unsigned int &n) const { return "zatial nic"; /* DOROBIT*/ }
/// -------------------------------------------------------------------------------------------------------------------
Noesis::PropertyChangedEventHandler& LanguageModel::PropertyChanged() { return changed; }
/// -------------------------------------------------------------------------------------------------------------------
void LanguageModel::Changed(NsSymbol prop) { changed(this, Noesis::PropertyChangedEventArgs(prop)); }
Code: Select all
MainGrid::MainGrid()
{
this->SetDataContext(MyDelegate::m_LangModel);
}
Who is online
Users browsing this forum: Ahrefs [Bot] and 5 guests