The relative clause (which) in GF - gf

"Play Toy Story which was published last year"
Sentence = mkUtt( mkImp (mkVP
(mkV2 "play")
(mkNP (mkCN
(mkCN (mkN "Toy Story"))
(mkS pastTense simultaneousAnt(mkCl (mkVP
(mkV2 "publish")
(mkNP (mkCN (mkN "last yser")))
)))
))
));
When creating a relative clause sentence in GF it always the syntax S for sentence will add that between the two of the sentences is there is any way to replace that with which.

First of all, the structure you made isn't a relative clause, but this structure:
mkCN : CN -> S -> CN -- rule that she sleeps
Relative clause has the type RS in the RGL.
How to construct an actual RS
Here I build the RS gradually. Feel free to put these steps back to a single expression, if you wish so, but I find it clearer to to things like this.
oper
last_year_Adv : Adv = ParadigmsEng.mkAdv "last year" ;
published_last_year_VP : VP = mkVP (passiveVP (mkV2 "publish")) last_year_Adv ;
which_is_published_last_year_RCl : RCl = mkRCl which_RP published_last_year_VP ;
which_was_published_last_year_RS : RS = mkRS pastTense which_is_published_last_year_RCl ;
lin
play_TS = mkUtt (mkImp (mkVP
(mkV2 "play")
(mkNP
(mkNP (mkPN "Toy Story"))
which_was_published_last_year_RS)
)
) ;
Now when we test it on the GF shell, we see that despite the name, which_RP is actually "that".
> l play_TS
play Toy Story , that was published last year
How to change "that" into "which"
The first thing to check when you want to create a new lexical item is Paradigms module. Unfortunately, there is no mkRP for English. Things like relative pronouns are usually thought of as closed class: there's only a small, fixed amount of them. Other examples of closed classes are basic numerals (you can't just make up a new integer between 4 and 5!) and determiners. Contrast this to open classes like nouns, verbs and adjectives, those pop up all the time. For open classes, Paradigms modules have many options. But not for closed classes, like relative pronouns.
So if Paradigms doesn't help, the next thing to check is the language-specific Extra module.
Check language-specific Extra modules
If you have the RGL source on your own computer, you can just go to the directory gf-rgl/src/english and grep for which. Or you can use the RGL browser to search for interesting functions.
And there is indeed a relative pronoun in ExtraEng, also called which_RP. (There is also one called who_which_RP.) So now you can do these modifications in your grammar:
concrete MyGrammarEng of MyGrammar =
open SyntaxEng,
ParadigmsEng,
ExtraEng -- Need to open ExtraEng in the concrete!
in ** {
-- … as usual, except for
oper
which_is_published_last_year_RCl : RCl =
mkRCl ExtraEng.which_RP -- Use the ExtraEng.which_RP!
published_last_year_VP ;
And the rest of the code is like before. This produces the result you want.
> l play_TS
play Toy Story , which was published last year
Last-resort hack
So you have looked in all possible modules and found nothing. Consider making it into an issue in the gf-rgl repository, if it's something that's clearly wrong or missing.
But in any case, here's a general, unsafe hack to quickly construct what you want.
First, let's look at the lincat of RP in CatEng, {s : RCase => Str ; a : RAgr}. Then let's look at its implementation in RelativeEng. There you see also the explanation why it's always "that": unlike who and which, "that" works for animate and inanimate NPs.
So I would do this to force the string "which":
oper
myWhich_RP : RP = which_RP ** {s = table {_ => "which"}} ;
The ** syntax means record extension. We use all other fields from the original which_RP, but in the s field, we put a table whose all branches contain the string "which". (You can read more about this technique in my blog.)
Then we use the newly defined myWhich_RP in forming the relative clause:
oper
which_is_published_last_year_RCl : RCl = mkRCl myWhich_RP published_last_year_VP ;
This works too, but it's unsafe, because whenever the RGL changes, any code that touches the raw implementation may break.

Related

Subjunctive mood in Spanish in GF

What is the correct grammar tree in GF for generating sentences in Spanish:
a) that contain subjunctive mood.
b) which the subject is a sentence too.
an example:
me gusta que mi jefe no trabaje hoy
Let's construct this piece by piece.
bossDoesntWork_S : S = mkS negativePol (mkCl (mkNP i_Pron boss_N) work_V) ;
Checking out the table, we see that both indicative and subjunctive are retained.
> cc -table bossDoesntWork_S
s . CommonRomance.Indic => mi jefe no trabaja
s . CommonRomance.Conjunct => mi jefe no trabaje
So now we need to give this as an argument to some VS, which forces out the subjunctive. Let's construct one—there is a ready-made constructor in ParadigmsSpa, called subjVS : V -> VS.
likeThat_VS : VS = subjVS like_V ;
Now let's test that:
> cc -one mkS ( mkCl (mkNP i_Pron) likeThat_VS bossDoesntWork_S)
yo gusto que mi jefe no trabaje
The subjunctive is correct, but unfortunately, the dative agreement isn't working properly. That's a known issue, and I have tried to fix it, but adding it on top, in a way that everything works properly, makes the whole grammar just really slow. (I wonder if it was more feasible, if Spanish didn't use the Romance functor, but that's not something I'm willing to try. :-P)
The complete grammar
So, the subjunctive part of this is easy. Here's a grammar for you to try out.
resource Subjunctive = open SyntaxSpa, LexiconSpa, ParadigmsSpa in {
oper
likeThat_VS : VS = subjVS like_V ;
bossDoesntWork_S : S = mkS negativePol (mkCl (mkNP i_Pron boss_N) work_V) ;
-- lexicon
like_V : V = <like_V2 : V> ; --treat LexiconSpa.like_V2 as V
work_V : V = mkV "trabajar" ;
}
Note on dative verbs
So what to do with dative verbs? For V2, you can just flip the subject and the object. But for VS, it's trickier, and would require ~ugly~creative hacks.
For now, I would suggest postprocessing, as in this answer. The good side with a dative verb as a VS is that the verb will always inflect in 3rd person singular, so you don't have the situation like "me gustas tu" vs. "me gustan ustedes". You can safely postprocess "yo gusto que" into "me gusta que".
If the RGL is fixed to include proper handling of dative verbs, I'll update this answer.

How to keep translations separated where the same word is used in English but a different one in other languages?

Imagine I have a report, a letter actually, which I need to translate to several languages. I have created a greeting field in the form which is filled programatically by an onchange event method.
if self.partner_id.gender == 'female':
self.letter_greeting = _('Dear %s %s,') % ( # the translation should be "Estimada"
self.repr_recipient_id.title.shorcut, surname
)
elif self.partner_id.gender == 'male':
self.letter_greeting = _('Dear %s %s,') % ( # translation "Estimado"
self.repr_recipient_id.title.shorcut, surname
)
else:
self.letter_greeting = _('Dear %s %s,') % ( # translation: "Estimado/a"
self.partner_id.title.shorcut, surname
)
In that case the word Dear should be translated to different Spanish translations depending on which option is used, this is because we use different termination depending on the gender. Exporting the po file I found that all the options are altogether, that make sense because almost all the cases the translations will be the same, but not in this case:
#. module: custom_module
#: code:addons/custom_module/models/sale_order.py:334
#: code:addons/custom_module/models/sale_order.py:338
#: code:addons/custom_module/models/sale_order.py:342
#, python-format
msgid "Dear %s %s,"
msgstr "Dear %s %s,"
Solutions I can apply directly
Put all the terms in different entries to avoid the same translation manually every time I need to update the po file. This can be cumbersome if you have many different words with that problem. If I do it and I open the file with poedit, this error appears: duplicate message definition
Put all the possible combinations with slashes, this is done y some other parts of Odoo. For both gender would be:
#. module: stock
#: model:res.company,msg:stock.res_company
msgid "Dear"
msgstr "Estimado/a"
This is just an example. I can think of many words that look the same in English, but they use different spelling or meanings in other languages depending on the context.
Possible best solutions
I don't know if Odoo know anything aboutu the context of a word to know if it was already translated or not. Adding a context manually could solve the problem, at least for words with different meanings.
The nicest solution would be to have a parameter to the translation module to make sure that the word is exported as an isolated entry for that especific translation.
Do you think that I am giving to it too much importance haha? Do you know if there is any better solution? Why is poedit not taking into account that problem at all?
I propose an extension of models res.partner.title and res.partner.
res.partner.title should get a translateable field for saving salutation prefixes like 'Dear' or 'Sehr geehrter' (German). Maybe it's worth to get something about genders, too, but i won't get into detail here about that.
You probably want to show the configuring user an example like "Dear Mr. Name" or something like that. A computed field should work.
On res.partner you should just implement either a computed field or just a method to get a full salutation for a partner record.
To some degree this is a linguistics problem. I believe the best solution would be to use a different "Source Language", one made up of keys, and then have English as another Translation. The word "Dear" in English does not have a gender context (and typically, much of English doesn't), while the word "Estimado" in Spanish does. The translation from that Spanish word to English is more appropriately "Masculine Dear." Therefore, using keys as your source language, you would have this:
SourceText (EnglishDescription) -> Translation (English) -> Translation (Spanish)
DearMasculine -> Dear -> Estimado
DearFeminine -> Dear -> Estimada
DearNuetral -> Dear -> Estimado/a

adding (|) functionality to determiner on GF

On GF writing sentences' tree often encounter many options where multiple prepositions could be used in the same tree such as
Download it on my phone
Download it to my phone
Download it onto my phone
... and the list goes on and on.
this kind of problem could be solved as below
(on_Prep|to_Prep|...)
But in some situations, this problem occurs with determiners such as
Eat the food
Eat food
I know the meaning of the above sentences is not exactly the same but is there any way to accomplish such a goal?
I tried the following but it seemed unlogical.
mkNP
(the_Det|)
(mkN ("food"))
I also tried to add an empty string for determiner such as mkDet (mkDigits (""))
but unfortunately, the above two ways seem not smart enough.😁😁
Your general approach with using | is correct.
There is no empty determiner, but rather another overload instance of mkNP. There's one with a determiner (so Det -> N -> NP) and another without, just N -> NP. So you can do this:
eat_food_VP : VP =
mkVP eat_V2 (mkNP the_Det food_N | mkNP food_N) ;

Generating a Possession Genitive Case in GF

I checked the GF library for "’s" as in "My friend’s house", but I couldn't seem to find the right method to create such a relation. May someone guide me on this problem.
Appreciate it 🌹🌹
There's indeed no function for the 's possessive in the core RGL. The closest you can get using just the RGL API is "the house of my friend".
However, there is a module called Extend, which has a function GenNP : NP -> Quant.
So how to use Extend? You have been using the RGL API, where all of the mkX opers are available when you open the Syntax and Paradigms modules. The Extend module is much newer than the core RGL, so its functions are not shown in the synopsis. But you can use them just like you'd use the Syntax and Paradigms modules. Here's an example usage:
resource Test = open SyntaxEng, ParadigmsEng, LexiconEng, ExtendEng in {
oper
-- "the house of my friend"
house1 : NP = mkNP the_Det (mkCN (mkN2 house_N) (mkNP i_Pron friend_N)) ;
-- "my friend's house"
house2 : NP =
let myFriend : NP = mkNP i_Pron friend_N ;
myFriends : Quant = GenNP myFriend ; -- GenNP is from ExtendEng
in mkNP myFriends house_N ;
}
If you have any further questions on how to use Extend, I'll be glad to help!
Copy that into a file called Test.gf, and open your GF shell as you normally do. Then you can import the file with the flag -retain, that allows you to evaluate opers with the cc command. Like this:
(You need to be inside the GF shell, not on the command line)
> i -retain Test.gf
> cc -one house1
the house of my friend
> cc -one house2
my friend's house
If you search the English RGL for implementations of the genitive case (Gen for the most part), you may find something useful for your implementation.
For example, you have addGenitiveS in CompatibilityEng.gf and regGenitiveS in ResEng.gf.
> cc -table ResEng.regGenitiveS "dog"
ResEng.Nom => dog
ResEng.Gen => dog's

Am I training my wit.ai bot correctly?

I'm trying to train my Wit.ai bot in order to recognize the first name of someone. I'm not very sure if I well understand how the NLP works so I'll give you an example.
I defined a lot of expressions like "My name is XXXX", "Everybody calls me XXXX"
In the "Understanding" table I added an entity named "contact_name" and I add almost 50 keywords like "Michel, John, Mary...".
I put the trait as "free-text" and "keywords".
I'm not sure if this process is correctly. So, I ask you:
does it matter the context like "My name is..." for the NLP? I mean...will it help the bot to predict that after this expression probably a fist name will come on?
is that right to add like 50 values to an entity or it's completly wrong?
what do you suggest as a training process in order to get the first name of someone?
You have done it right by keeping the entity's search strategy as "free-text" and "Keywords". But Adding keywords examples to the entity doesn't make any sense because a person's name is not a keyword.
So, I would recommend a training strategy which is as follows:
Create various templates of the message like, "My name is XYZ", "I am XYZ", "This is XYZ" etc. (all possible introduction messages you could think of)
Remove all keywords and expressions for the entity you created and add these two keywords:
"a b c d e f g h i j k l m n o p q r s t u v w x y z"
"XYZ" (can give any name but maintain this name same for validating the templates)
In the 'Understanding' tab enter the messages and extract the name into the entity ("contact_name" in your case) and validate them
Similarly, validate all message templates keeping the name as "XYZ"
After you have done this for all templates your bot will be able to recognise any name in a given template of the message
The logic behind this is your entity is a free-text and keyword which means it first tries to match the keyword if not matched it tries to find the word in the same position of the templates. Keeping the name same for validations helps to train the bot with the templates and learn the position where the name will be usually found.
Hope this works. I have tried this and worked for me. I am not sure how bot trains in background. I recommend you to start a new app and do this exercise.
Comment if there is any problem.
wit.ai has a pre-trained entity extraction method called wit/contact, which
Captures free text that's either the name or a clear reference to a
person, like "Paul", "Paul Smith", "my husband", "the dentist".
It works good even without any training data.
To read about the method refer to duckling.