It would be helpful if you could say what " does not work" means in practice
I hope the following comments help solve the problem.
As feature file syntax, your syntax is correct, and will build a properly formed lookup.
One reason that it may not work is how the feature is applied. I see that the
http://partners.adobe.com/asn/tech/type/opentype/appendices/features_fj.jsp#fina
says of 'fina' that;
Recommended implementation: The fina table maps default alphabetic forms to corresponding ending forms (GSUB lookup type 1).
meaning that it does only a one to one substitution.
There are two ways to get there.
1) do a ligature substitution first
feature liga {
sub n t by n_t;
}
feature fina {
sub n_t by n_t.end;
}
However, this requires both features to be on. Since this looks like a an alternate form that it is not required, and requires context, I think it would be reasonable to put in the clig feature, and simulate end-end-of-word matching yourself. This is what we do for end-of-word ligatures in script fonts. It is something of a hack, but in the absence of "end of word" marks, it is the best that can be done.. To do this, you first use an 'ignore' rule to match all non-end of word conditions, and and then put your substitution rules after that.
@LETTERS = [ < all letters in the font that could be part of a word>];
feature clig {
lookup BEGIN_WORD_LIGS {
ignore @LETTERS @LETTERS'; # will match any word glyph preceeded by another word glyph.
sub c t by c_t.begin; # you know that there is no word glyph before the 'ct' sequence.
};
lookup END_WORD_LIGS {
ignore @LETTERS' @LETTERS; # will match any word glyph followed by another word glyph.
sub o f f by o_f_f.end; # you know that there is no word glyph after the 'off' sequence.
};
} clig;
Since each lookup is applied to the entire text string from beginning to end in turn, an 'ignore' rule shelters only the rules that follow it in the same lookup.