Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
508c765
# This is a combination of 25 commits.
deonajulary06 May 27, 2025
a3b2bfe
Inflection 85: Add language support and grammar synthesis for Malayalam
deonajulary06 Aug 20, 2025
03dcebf
Inflection-120 Update ICU version in versions.mk to 77.1 (#119)
FrankYFTang May 30, 2025
d8afea0
Add Factory for MF2 ( issues/117 ) (#114)
FrankYFTang Jun 4, 2025
9f7a3c5
Add checkleak ci to use valgrind. Fix issues/118 (#121)
FrankYFTang Jun 5, 2025
e421230
Fix memory leak in MF2Factory.cpp (issue/131) (#132)
FrankYFTang Jun 27, 2025
5dd7985
Issue 134, use std::unique_ptr in SemanticFeatureModel (#137)
FrankYFTang Jun 27, 2025
e3b633a
Issue 134, use std::unique_ptr in (De|It)CommonConceptFactory.cpp (#136)
FrankYFTang Jun 27, 2025
46da4d8
Issue 134, use std::unique_ptr in RuCommonConceptFactory.cpp (#135)
FrankYFTang Jun 27, 2025
2554b1a
Inflection 134 std::unique_ptr for Chunk.cpp (#145)
FrankYFTang Jun 27, 2025
643e995
Inflection 134 std::unique_ptr for TokenExtractor (#144)
FrankYFTang Jun 28, 2025
74559c4
Inflection 140: Change the build process to also build on merging (#139)
FrankYFTang Jun 30, 2025
81acd79
Inflection 134 std::unique_ptr for DictionaryMetaData.cpp (#143)
FrankYFTang Jun 30, 2025
716f57e
Inflection 134 std::unique_ptr for DictionaryKeyIterator.cpp (#142)
FrankYFTang Jun 30, 2025
0cc07b4
Inflection 134 std::unique_ptr for KoGrammarSynthesizer_ParticleResol…
FrankYFTang Jun 30, 2025
3eefc23
Cache LFS content (fix issue/127) (#128)
FrankYFTang Jun 30, 2025
fe21c6e
WiP Add doxygen (#146)
FrankYFTang Jul 1, 2025
e9ca591
Change namespace in message2 (issue/147) (#148)
FrankYFTang Jul 2, 2025
7e3b8ec
Fix doxygen configuraiton (#149)
FrankYFTang Jul 2, 2025
832c176
Correct path to README.md and include that into the API doc. (#150)
FrankYFTang Jul 2, 2025
705f509
Fix some warning in doxygen (issue 147) (#151)
FrankYFTang Jul 7, 2025
763adfe
Update README.md (#153)
FrankYFTang Jul 8, 2025
663a5f8
Add comment for super class documentation Fix 147 (#152)
FrankYFTang Jul 8, 2025
307e8b6
Fix doxygen warning for DisplayValue (#154)
FrankYFTang Jul 8, 2025
6b24d9e
fix mistake in PR 152 (issue 147) (#156)
FrankYFTang Jul 8, 2025
5a07a94
Update DisplayValue.hpp (#157)
FrankYFTang Jul 8, 2025
e4e363d
fix doxygen warning in SemanticFeatureModel_DisplayData.hpp (issue 14…
FrankYFTang Jul 8, 2025
196cabf
Fix the doxygen warnings (issue 147) (#159)
FrankYFTang Jul 8, 2025
2f3a3ac
Create distribution packages for ubuntu (.deb release v0.0.1) (#129)
dockerh Jul 14, 2025
333b92d
issue 163 fix ULocale < and > operator order (#164)
FrankYFTang Jul 15, 2025
66a2b8b
Fix GitHub Release Trigger, ICU Cache Cleanup, and Artifact Upload (…
dockerh Jul 22, 2025
d2a3b36
Add operator<=> and remove operator< operator and compareTo function …
FrankYFTang Jul 22, 2025
719d459
Inflection 134 Use std::unique_ptr to avoid delete (#162)
FrankYFTang Jul 22, 2025
3425424
Fail doxygen warning (#161)
FrankYFTang Jul 29, 2025
ec6f078
Inflection-63 Integrate ko Wikidata into Unicode Inflection Inflectio…
grhoten Jul 31, 2025
2696ca3
Fix incorrect cache key (#170)
FrankYFTang Aug 5, 2025
bf1d1d6
Changed files based on comments
deonajulary06 Aug 20, 2025
19e2e50
Quick fix
deonajulary06 Aug 21, 2025
9ecedc2
Merge branch 'main' into update-new-language-doc
deonajulary06 Aug 21, 2025
65d0f3b
Restore Malayalam dictionary + inflectional data after LFS migrate
deonajulary06 Aug 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions documents/how_to_add_new_language.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ The following steps with help you identify files that need to be added or change
NOTE: Take a look at [PR #40](https://github.com/unicode-org/inflection/pull/40) and [PR #111](https://github.com/unicode-org/inflection/pull/111) for example on how to add initial language support based on dictionary lookup only.
In general, to bootstrap your progress look for grammatically similar language that's already supported, e.g. if you are adding Serbian look for existing Russian implementation.
This will help you find most of the files you need to add/change and will speed up implementation of the rules and lexicons.
We recommend you spend around a week researching the language and all the different components of the language before even beginning to modify and add the files below. Look at all the files in the project such as tokenizers, configuration files, grammar files, and different lookup functions to see what you need. This will save you a lot of time in the end. We highly suggest you stray away from hardcoded logic and rely on the Dictionary Lookup. Look at all the grammemes, tokenizer logic, and multi-word phrase handling.

Before you add new language support, go to the README.md in the inflection subfolder (inflection/inflection/README.md), build the project, and make sure all the tests run on your computer.

## Mark your language as supported
* UPDATE: inflection/src/inflection/util/LocaleUtils.hpp
Expand All @@ -29,13 +32,13 @@ TODO: We need to expand what each of these do.
* ADD: inflection/src/inflection/grammar/synthesis/*Xx*GrammarSynthesizer.hpp
* ADD: inflection/src/inflection/grammar/synthesis/*Xx*GrammarSynthesizer.cpp
* ADD: inflection/src/inflection/grammar/synthesis/*Xx*GrammarSynthesizer_*Xx*DisplayFunction.hpp
* ADD: inflection/src/inflection/grammar/synthesis/*Xx*GrammarSynthesizer_*Xx*DisplayFunction.hpp
* ADD: inflection/src/inflection/grammar/synthesis/*Xx*GrammarSynthesizer_*Xx*DisplayFunction.cpp
* UPDATE: inflection/src/inflection/grammar/synthesis/GrammarSynthesizerFactory.cpp
* UPDATE: inflection/src/inflection/grammar/synthesis/fwd.hpp

## Add language specific properties for lists, quantities and related topics
* ADD: inflection/src/inflection/dialog/language/*Xx*CommonConceptFactory.hpp
* ADD: inflection/src/inflection/dialog/language/*Xx*CommonConceptFactory.hpp
* ADD: inflection/src/inflection/dialog/language/*Xx*CommonConceptFactory.cpp
* UPDATE: inflection/src/inflection/dialog/language/fwd.hpp

## Define and create lexion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ dictionary_he.lst filter=lfs diff=lfs merge=lfs -text
dictionary_hi.lst filter=lfs diff=lfs merge=lfs -text
dictionary_it.lst filter=lfs diff=lfs merge=lfs -text
dictionary_ko.lst filter=lfs diff=lfs merge=lfs -text
dictionary_ml.lst filter=lfs diff=lfs merge=lfs -text
dictionary_nb.lst filter=lfs diff=lfs merge=lfs -text
dictionary_nl.lst filter=lfs diff=lfs merge=lfs -text
dictionary_pt.lst filter=lfs diff=lfs merge=lfs -text
Expand All @@ -23,6 +24,7 @@ inflectional_fr.xml filter=lfs diff=lfs merge=lfs -text
inflectional_he.xml filter=lfs diff=lfs merge=lfs -text
inflectional_hi.xml filter=lfs diff=lfs merge=lfs -text
inflectional_it.xml filter=lfs diff=lfs merge=lfs -text
inflectional_ml.xml filter=lfs diff=lfs merge=lfs -text
inflectional_nb.xml filter=lfs diff=lfs merge=lfs -text
inflectional_nl.xml filter=lfs diff=lfs merge=lfs -text
inflectional_pt.xml filter=lfs diff=lfs merge=lfs -text
Expand Down
Git LFS file not shown
Git LFS file not shown
100 changes: 100 additions & 0 deletions inflection/resources/org/unicode/inflection/features/grammar.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1624,6 +1624,106 @@
</category>
</grammar>
</language>
<language id="ml">
<grammar>
<category name="case">
<grammeme name="nominative"/> <!-- no explicit marker; subject form -->
<grammeme name="accusative"/> <!-- -യെ, -ായെ, marks direct object -->
<grammeme name="genitive"/> <!-- -ന്റെ, -യുടെ (possessive) -->
<grammeme name="dative"/> <!-- -ക്ക്, -ന് (to/for) -->
<grammeme name="instrumental"/> <!-- -ആല് (by means of) -->
<grammeme name="locative"/> <!-- -യില് (in/at) -->
<grammeme name="sociative"/> <!-- -ഓടു് (along with) -->
</category>
<category name="number">
<grammeme name="singular"/>
<grammeme name="plural"/>
</category>
<category name="animacy">
<grammeme name="animate"/>
<grammeme name="inanimate"/>
<grammeme name="human"/>
</category>
Comment on lines +1642 to +1646
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the same indentation level as the other categories. The indentation is 4 spaces.

<category name="pos">
<grammeme name="pronoun"/>
<grammeme name="verb"/>
<grammeme name="noun"/>
<grammeme name="adjective"/>
</category>
<category name="person">
<restrictions>
<restriction name="pos" value="pronoun"/>
<restriction name="pos" value="verb"/>
</restrictions>
<grammeme name="first"/>
<grammeme name="second"/>
<grammeme name="third"/>
</category>
<category name="gender">
<restrictions>
<restriction name="pos" value="pronoun"/>
<restriction name="pos" value="verb"/>
<restriction name="pos" value="noun"/>
</restrictions>
<grammeme name="masculine"/>
<grammeme name="feminine"/>
<grammeme name="neuter"/> <!-- e.g. for objects or animals -->
</category>
<category name="tense">
<restrictions>
<restriction name="pos" value="verb"/>
</restrictions>
<grammeme name="past"/>
<grammeme name="present"/>
<grammeme name="future"/>
</category>
<category name="form">
<grammeme name="infinitive"/>
<grammeme name="participle"/>
</category>
<category name="determination">
<restrictions>
<restriction name="pos" value="pronoun"/>
<restriction name="case" value="genitive"/>
</restrictions>
<grammeme name="independent"/> <!-- e.g. mine -->
<grammeme name="dependent"/> <!-- e.g. my {object} -->
</category>
<category name="mood">
<restrictions>
<restriction name="pos" value="verb"/>
</restrictions>
<grammeme name="indicative"/>
<grammeme name="imperative"/>
<grammeme name="subjunctive"/>
</category>
<category name="pronounType">
<restrictions>
<restriction name="pos" value="pronoun"/>
</restrictions>
<grammeme name="personal"/> <!-- regular pronouns like ഞാൻ, നീ -->
<grammeme name="reflexive"/> <!-- e.g. താൻ, തങ്ങൾ -->
<grammeme name="proximal"/> <!-- e.g. ഇവൻ, ഇവൾ, ഇത് -->
<grammeme name="distal"/> <!-- e.g. അവൻ, അവൾ, അത് -->
<grammeme name="interrogative"/> <!-- e.g. എവൻ, എവൾ, ഏത് -->
</category>
<category name="formality">
<restrictions>
<restriction name="pos" value="verb"/>
<restriction name="pos" value="pronoun"/>
</restrictions>
<grammeme name="formal"/>
<grammeme name="informal"/>
</category>
<category name="clusivity">
<restrictions>
<restriction name="pos" value="pronoun"/>
</restrictions>
<grammeme name="inclusive"/>
<grammeme name="exclusive"/>
</category>
</grammar>
</language>
<language id="ms">
<grammar>
<category name="clusivity">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
അവൻ,third,singular,nominative,masculine,personal,distal
എനിക്ക്,first,singular,dative,personal
ഞാൻ,first,singular,nominative,exclusive,personal
എന്നെ,first,singular,accusative,exclusive,personal
എന്റെ,first,singular,genitive,determination=dependent,exclusive,personal
എന്റേത്,first,singular,genitive,determination=independent,exclusive,personal
Comment on lines +5 to +6
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The determination= is unnecessary. You can remove it.

നമ്മെ,first,plural,accusative,inclusive,personal
നമുക്ക്,first,plural,dative,inclusive,personal
ഞങ്ങൾ,first,plural,nominative,exclusive,personal
ഞങ്ങളെ,first,plural,accusative,exclusive,personal
ഞങ്ങൾക്ക്,first,plural,dative,exclusive,personal
ഞങ്ങളുടെ,first,plural,genitive,exclusive,determination=dependent,personal
ഞങ്ങളുടേത്,first,plural,genitive,exclusive,determination=independent,personal
നമ്മുടെ,first,plural,genitive,inclusive,determination=dependent,personal
നമ്മുടേതു്,first,plural,genitive,inclusive,determination=independent,personal
നിനക്ക്,second,singular,dative,informal,personal
നീ,second,singular,nominative,informal,personal
നിനെ,second,singular,accusative,informal,personal
നിന്റെ,second,singular,genitive,informal,determination=dependent,personal
നിന്റേതു്,second,singular,genitive,informal,determination=independent,personal
താങ്കൾ,second,singular,nominative,formal,personal
താങ്കളെ,second,singular,accusative,formal,personal
താങ്കൾക്ക്,second,singular,dative,formal,personal
താങ്കളുടെ,second,singular,genitive,formal,determination=dependent,personal
താങ്കളുടേതു്,second,singular,genitive,formal,determination=independent,personal
നിങ്ങൾ,second,plural,nominative,formal,personal
നിങ്ങളെ,second,plural,accusative,formal,personal
നിങ്ങൾക്ക്,second,plural,dative,formal,personal
നിങ്ങളുടെ,second,plural,genitive,formal,determination=dependent,personal
നിങ്ങളുടേതു്,second,plural,genitive,formal,determination=independent,personal
അവനെ,third,singular,accusative,masculine,personal,distal
അവന്റെ,third,singular,genitive,masculine,determination=dependent,personal,distal
അവന്റെത്,third,singular,genitive,masculine,determination=independent,personal,distal
അവൾ,third,singular,nominative,feminine,personal,distal
അവളെ,third,singular,accusative,feminine,personal,distal
അവളുടെ,third,singular,genitive,feminine,determination=dependent,personal,distal
അവളുടേതു്,third,singular,genitive,feminine,determination=independent,personal,distal
അത്,third,singular,nominative,neuter,personal,distal
അതിനെ,third,singular,accusative,neuter,personal,distal
അതിന്റെ,third,singular,genitive,neuter,determination=dependent,personal,distal
അതിന്റേതു്,third,singular,genitive,neuter,determination=independent,personal,distal
അവർ,third,plural,nominative,personal,distal
അവരെ,third,plural,accusative,personal,distal
അവരുടെ,third,plural,genitive,determination=dependent,personal,distal
അവരുടേതു്,third,plural,genitive,determination=independent,personal,distal
എന്നിൽ,first,singular,locative,personal
എന്നാൽ,first,singular,instrumental,personal
എന്നോടു്,first,singular,sociative,personal
ഞങ്ങളിലു്,first,plural,locative,exclusive,personal
ഞങ്ങളാൽ,first,plural,instrumental,exclusive,personal
ഞങ്ങളോടു്,first,plural,sociative,exclusive,personal
നിനിൽ,second,singular,locative,informal,personal
നിനാൽ,second,singular,instrumental,informal,personal
നിനോടു്,second,singular,sociative,informal,personal
താങ്കളിൽ,second,singular,locative,formal,personal
താങ്കളാൽ,second,singular,instrumental,formal,personal
താങ്കളോടു്,second,singular,sociative,formal,personal
നിങ്ങളിൽ,second,plural,locative,formal,personal
നിങ്ങളാൽ,second,plural,instrumental,formal,personal
നിങ്ങളോടു്,second,plural,sociative,formal,personal
അവനിൽ,third,singular,locative,masculine,personal,distal
അവനാൽ,third,singular,instrumental,masculine,personal,distal
അവനോടു്,third,singular,sociative,masculine,personal,distal
അവളിൽ,third,singular,locative,feminine,personal,distal
അവളാൽ,third,singular,instrumental,feminine,personal,distal
അവളോടു്,third,singular,sociative,feminine,personal,distal
അതിൽ,third,singular,locative,neuter,personal,distal
അതാൽ,third,singular,instrumental,neuter,personal,distal
അതോടു്,third,singular,sociative,neuter,personal,distal
അവരിൽ,third,plural,locative,personal,distal
അവരാൽ,third,plural,instrumental,personal,distal
അവരോടു്,third,plural,sociative,personal,distal
താൻ,third,singular,nominative,reflexive,personal
തങ്ങൾ,third,plural,nominative,formal,reflexive,personal
ഇവൻ,third,singular,nominative,masculine,proximal,personal
ഇവൾ,third,singular,nominative,feminine,proximal,personal
ഇത്,third,singular,nominative,neuter,proximal,personal
ഇവർ,third,plural,nominative,proximal,personal
എവൻ,third,singular,nominative,masculine,interrogative
എവൾ,third,singular,nominative,feminine,interrogative
എവർ,third,plural,nominative,interrogative
ഏത്,third,singular,nominative,neuter,interrogative
നാം,first,plural,nominative,inclusive,personal
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ locale.group.it=it_IT,it_CH
locale.group.ja=ja_JP
locale.group.ko=ko_KR
locale.group.ms=ms_MY
locale.group.ml=ml_IN
locale.group.nb=nb_NO
locale.group.nl=nl_NL,nl_BE
locale.group.pt=pt_BR,pt_PT
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# Copyright 2025 Unicode Incorporated and others. All rights reserved.
#
tokenizer.implementation.class=DefaultTokenizer
tokenizer.nonDecompound.file=/org/unicode/inflection/tokenizer/ml/nondecompound.tok
tokenizer.decompound=(ശ്രീ)(.+?)(ഗുരു|സര്‍ക്കാര്‍)$|^(.+?)(ഗുരു|സര്‍ക്കാര്‍)$|^(.+?)(ഉണ്ട്|ആണ്|ഇല്ല)$|^(.+?)(ഒടൊപ്പം|ഉടൻ|ഓടെ|ഓട്|ഒപ്പം|തന്നെ|പോലും|പോലെ|ഉം|യ്)$|^(.+?)(കളുടെ|ങ്ങളുടെ|ത്തിന്റെ|ൻ്റെ|ന്റെ|യുടേ|യുടെ|യാൽ|യിൽ|ഇൽ|ല്|ൽ|ക്ക്|മാർ|ങ്ങൾ|കൾ|നെ|യെ)

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
അമ്മ
അച്ഛൻ
അച്ഛി
അമ്മൻ
മകൻ
മകൾ
കുട്ടി
കുട്ടികൾ
ആൺകുട്ടി
ആൺകുട്ടികൾ
പെൺകുട്ടി
പെൺകുട്ടികൾ
കഥ
ചിത്രം
ചിത്രങ്ങൾ
ഗ്രന്ഥം
ഗ്രന്ഥങ്ങൾ
മക്കൾ
ഞാൻ
നീ
നിങ്ങൾ
അവൻ
അവൾ
അവ
അവർ
ഇത്
അത്
ഇവ
അവ
ശ്രീ
നാരായണ
ഗുരു
കേരളം
സര്‍ക്കാര്‍
കേരളസര്‍ക്കാര്‍
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2025 Unicode Incorporated and others. All rights reserved.
*/

#include <inflection/dialog/language/MlCommonConceptFactory.hpp>
#include <inflection/dialog/SemanticFeatureConceptBase.hpp>
#include <inflection/dialog/SpeakableString.hpp>
#include <inflection/dialog/SemanticConceptList.hpp>
#include <inflection/dialog/Plurality.hpp>

namespace inflection::dialog::language {

// Malayalam-specific conjunction for OR
::inflection::dialog::SemanticConceptList* MlCommonConceptFactory::createOrList(
const ::std::vector<const ::inflection::dialog::SemanticFeatureConceptBase*>& concepts) const
{
auto list = super::createOrList(concepts);
if (list) {
list->setBeforeLast(::inflection::dialog::SpeakableString(u" അല്ലെങ്കിൽ "));
}
return list;
}

// Malayalam-specific conjunction for AND
::inflection::dialog::SemanticConceptList* MlCommonConceptFactory::createAndList(
const ::std::vector<const ::inflection::dialog::SemanticFeatureConceptBase*>& concepts) const
{
auto list = super::createAndList(concepts);
if (list) {
list->setBeforeLast(::inflection::dialog::SpeakableString(u"യും "));
list->setItemDelimiter(::inflection::dialog::SpeakableString(u", "));
}
return list;
}

// In Malayalam, numbers generally follow the noun
::inflection::dialog::SpeakableString
MlCommonConceptFactory::quantifiedJoin(const ::inflection::dialog::SpeakableString& formattedNumber,
const ::inflection::dialog::SpeakableString& nounPhrase,
const ::std::u16string& /*measureWord*/,
Plurality::Rule countType) const
{
::inflection::dialog::SpeakableString space(u" ");
if (countType == Plurality::Rule::ONE) {
return nounPhrase + space + formattedNumber;
}
return formattedNumber + space + nounPhrase;
}

// Fallback to base implementation for now
::inflection::dialog::SpeakableString
MlCommonConceptFactory::quantifyType(const ::inflection::dialog::SpeakableString& formattedNumber,
const ::inflection::dialog::SemanticFeatureConceptBase& semanticConcept,
bool useDefault,
::inflection::dialog::Plurality::Rule countType) const
{
return super::quantifyType(formattedNumber, semanticConcept, useDefault, countType);
}

} // namespace inflection::dialog::language
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2025 Unicode Incorporated and others. All rights reserved.
*/
#pragma once

#include <inflection/dialog/language/fwd.hpp>
#include <inflection/dialog/CommonConceptFactoryImpl.hpp>
#include <inflection/grammar/synthesis/fwd.hpp>
#include <inflection/dialog/Plurality.hpp>

namespace inflection::dialog::language {

class MlCommonConceptFactory : public CommonConceptFactoryImpl {
using super = CommonConceptFactoryImpl;

public:
explicit MlCommonConceptFactory(const ::inflection::util::ULocale& language);
~MlCommonConceptFactory() override;

// Malayalam-specific conjunction handling
::inflection::dialog::SemanticConceptList* createOrList(
const ::std::vector<const ::inflection::dialog::SemanticFeatureConceptBase*>& concepts) const override;

::inflection::dialog::SemanticConceptList* createAndList(
const ::std::vector<const ::inflection::dialog::SemanticFeatureConceptBase*>& concepts) const override;

protected:
::inflection::dialog::SpeakableString quantifiedJoin(
const ::inflection::dialog::SpeakableString& formattedNumber,
const ::inflection::dialog::SpeakableString& nounPhrase,
const ::std::u16string& measureWord,
::inflection::dialog::Plurality::Rule countType) const override;

::inflection::dialog::SpeakableString quantifyType(
const ::inflection::dialog::SpeakableString& formattedNumber,
const ::inflection::dialog::SemanticFeatureConceptBase& semanticConcept,
bool useDefault,
::inflection::dialog::Plurality::Rule countType) const override;
};

} // namespace inflection::dialog::language
Loading
Loading