Files
Alessandro Colace 97bdabe9dc Allow lang and region scoping for Ticker via YfConfig
Yahoo's v7 (`/v7/quote`) and v10 (`/quoteSummary`) endpoints accept
`lang` and `region` parameters and return localized fields (`longName`,
`shortName`, ...) when the ticker has been translated for that locale —
e.g. 1810.HK returns '小米集團-W' under `lang=zh-Hant-HK`, GAZP.ME
returns 'Публичное акционерное общество Газпром' under `lang=ru-RU`.
Previously these params were not exposed and `Ticker.info["longName"]`
always came back in U.S. English.

Surfaced as global config (`YfConfig.locale.lang` / `YfConfig.locale.region`)
rather than per-Ticker constructor params: a typical user wants the
same locale for every call in their session, and the config approach
also covers the v10 calendar/earnings endpoint in `_fetch_history_metadata`
without threading kwargs through three layers.

- Add `YfConfig.locale.lang` (default `"en-US"`) and `YfConfig.locale.region`
  (default `"US"`).
- `Quote._fetch` (v10/quoteSummary) and `Quote._fetch_additional_info`
  (v7/quote) read the locale from `YfConfig` on every call.
- `_fetch_history_metadata` (v1 calendar) reads the same locale, replacing
  a hardcoded `lang=en-US, region=US`.
- The `v8/chart` endpoint ignores `lang` server-side, so we don't forward
  there — would only generate noise.
- Verified live for Latin/diacritics (it-IT), CJK (zh-Hant-HK, ja-JP),
  Cyrillic (ru-RU); Apple under ja-JP correctly stays "Apple Inc." since
  it's a U.S. listing.

Closes #2582
2026-05-15 17:13:22 +02:00

62 lines
1.5 KiB
Python

import json
class NestedConfig:
def __init__(self, name, data):
self.__dict__['name'] = name
self.__dict__['data'] = data
def __getattr__(self, key):
return self.data.get(key)
def __setattr__(self, key, value):
self.data[key] = value
def __len__(self):
return len(self.__dict__['data'])
def __repr__(self):
return json.dumps(self.data, indent=4)
class ConfigMgr:
def __init__(self):
self._initialised = False
def _load_option(self):
self._initialised = True # prevent infinite loop
self.options = {}
# Initialise defaults
n = self.__getattr__('network')
n.proxy = None
n.retries = 0
d = self.__getattr__('debug')
d.hide_exceptions = True
d.logging = False
loc = self.__getattr__('locale')
loc.lang = "en-US" # BCP-47 language tag for Yahoo v7/v10 endpoints
loc.region = "US" # ISO 3166-1 alpha-2 country code
def __getattr__(self, key):
if not self._initialised:
self._load_option()
if key not in self.options:
self.options[key] = {}
return NestedConfig(key, self.options[key])
def __contains__(self, key):
if not self._initialised:
self._load_option()
return key in self.options
def __repr__(self):
if not self._initialised:
self._load_option()
all_options = self.options.copy()
return json.dumps(all_options, indent=4)
YfConfig = ConfigMgr()