normalize_company_name() previously applied German conventions only. It now
covers German, French, Italian and English, which is what multilingual
registers such as the Swiss one require.
lang argument on normalize_company_name() and match_companies(),
accepting any of "de", "fr", "it", "en". Defaults to all four; narrow
it for single-language data to strip fewer tokens. The default therefore
strips more than in 0.1.x — pass lang = "de" for the old scope.sarl, sasu, eurl, societe, srl, snc, scarl, societa,
llp, incorporated, succursale, niederlassung, ...).company_name_stopwords() returns exactly which tokens are stripped for
a given set of languages, so the normalizer can be audited.Société and Sàrl were previously
never recognised on the first pass, because the patterns were matched against
the still-accented string.normalize_company_name() is now idempotent — applying it to its own
output is a no-op, so one pass always suffices. This follows from the
ordering fix above: previously Nestlé Sàrl became nestle sarl on the
first pass and only lost sarl on the second, so callers had to re-normalize
in a loop until the result stopped changing. Such loops can now be replaced
by a single call. A regression test locks the property in.S.A.R.L. becomes sarl
(and is stripped) instead of four stray letters s a r l. Dots after
multi-letter tokens still act as separators, so Co. KG is unaffected.L'Oréal and Loreal both normalize to loreal, and
McDonald's gives mcdonalds rather than mcdonald s.Deutsche Bank still normalizes
to deutsche bank, not bank.deutschland and
germany). They identify a firm as often as they pad it: removing them turned
Credit Suisse into credit and Air France into air, either of which can
then exact-match an unrelated company. Since a spurious exact match is trusted
and never reaches the fuzzy stages or the LLM validator, keeping them is the
safer default. Structural branch markers (Niederlassung, Succursale,
Filiale, Standort) are still removed.extra_stopwords argument on normalize_company_name() and
match_companies() for corpus-specific filler — use it to strip geography
anyway, e.g. extra_stopwords = c("deutschland", "schweiz").normalize_company_name() is lossy by design: "Meier GmbH" and "Meier AG"
both become "meier". Previously match_companies() aborted whenever
normalization produced duplicate dictionary names, which made it unusable on
real dictionaries without hand-written pre-cleaning.
match_companies() now collapses duplicate normalized names instead of
aborting. Each group is matched once against a representative row, and no
original row is lost:
dict_id in the result is the representative (first) id of the group.dict_id_all column lists every id in the group, separated by "|".n_dict_ids column reports the group size (1 when unambiguous).dict_crosswalk() returns the mapping from every original dictionary row
to its representative, so collapsed entries always remain traceable.expand_matches() expands a result to one row per original dictionary
row, recovering the source strings behind a collapsed group.on_duplicate argument. The default "collapse" is the behaviour above;
"error" restores the previous strict abort.NA after normalization are now dropped with a
warning. Previously an empty string could "exactly match" every other empty
string, producing spurious matches.dict_norm and query_norm arguments let you skip normalization on
either side when the input is already clean.match_companies() now returns query_name and dict_name alongside the
ids, so the result is readable (and ready for validate_matches_llm())
without joining the inputs back on. The set of returned columns has changed;
code that relied on the previous three-column output may need updating.match_type
column was referenced before it was created). All engines now return a
consistently typed empty result.block, fts_q) to their
inputs by reference.LazyData from DESCRIPTION (the package ships no data/
directory); added URL and BugReports. Fixed a dead reference URL and
retitled the package, which is no longer German-only.validate_matches_llm enabling it to connect to local LLM instances (like Ollama or LM Studio).engine argument allowing choice between "azure", "openai", or "local".validate_matches_llm writes to tempdir() by default.