Compare commits

..
333 Commits
Author SHA1 Message Date
renovate-bot adebd27ae0 chore(deps): update dependency naudio.winmm to v3
Build / Build (Release) (pull_request) Successful in 34s
Security Scan (reusable) / Security Scan (pull_request) Successful in 30s
Security / scan (pull_request) Successful in 30s
2026-08-20 00:35:19 +00:00
JonKazama-Hellion 6e24885241 docs: the privacy claim gets stronger, so the documents have to say so
Security Scan (reusable) / Security Scan (push) Successful in 24s
Security / scan (push) Successful in 24s
Build / Build (Release) (push) Successful in 26s
Removing BetterTTV took out the plugin's only outbound network call, and five
documents were still describing it as present. PRIVACY.md led with "one outbound
network call exists by design" -- the opposite of what shipped an hour ago, and
the one claim in that file people actually check.

PRIVACY.md now opens with none at all. The section that described the call is
kept and marked as removed rather than deleted, so the claim can be read against
what it replaced: the startup fetch meant BetterTTV saw an IP as soon as the
plugin loaded, whether an emote ever appeared or not. Worth leaving visible.
BetterTTV also comes out of the third-party table, which now lists only the two
parties nobody using this plugin through Dalamud can avoid.

SECURITY.md listed the EmoteCache HTTP client as in scope for reports. There is
nothing there to report on.

THIRD_PARTY_NOTICES.md named the call as current; both entries it has ever
carried are now historical.

README dropped the pointer to the outbound call and the switch for it, a
stability bullet about a crash fix in code that no longer exists, and the line in
the Chat 2 migration that moved an emote cache directory nothing reads.

ROADMAP gained 2.0.1 and 2.0.2, and a section for what the 2.0.0 push left
behind: 47 overlong comment blocks, channel names translated in only ten of the
25 languages, an orphaned EmoteCacheV1 directory on anyone who ran an older
build, and the deprecated GlobalScaleSafe call that is the last compiler warning
in the build.
2026-08-19 23:41:23 +02:00
JonKazama-Hellion 16730d5ed9 chore(release): 2.0.2 -- BetterTTV out, placeholders fixed
Forge Announce / Post changelog to Hellion Forge (push) Successful in 9s
Security Scan (reusable) / Security Scan (push) Successful in 27s
Security / scan (push) Successful in 27s
Build / Build (Release) (push) Successful in 34s
Release / Build and attach release ZIP (push) Successful in 31s
BetterTTV emote support is removed rather than switched off. Its shared-emote
endpoint went behind authentication and that is where nearly all of them came
from; what was left is the 65-entry global set, eleven of those on the plugin's
own known-broken list, so 54 largely static images from Twitch's early days.
Exactly one is animated, and that one is 492 frames at 140x140 -- 37 MB of
texture memory for a single emote, uploaded one frame at a time. Not worth a
network call and an on-disk cache on every start.

Gone with it: the download path, the cache directory, the GIF renderer, the
settings section, the block list, and 13 translation keys across 50 resource
files. 1567 lines. The plugin now makes no outbound network calls at all, which
is the claim PRIVACY.md has always wanted to make without an asterisk.

EmotePayload and its MessagePack type byte stay, deliberately. Around a thousand
rows in a two-month-old database carry them, and dropping the type would make
those fail to deserialise -- the history is the one thing 2.0.0 promised not to
touch. Nothing writes one any more and a stored emote renders as the code that
was typed, which is what the sender saw when they typed it.

Five descriptions in the Window tab printed {0} where the plugin name belonged,
handed to the widget directly instead of through string.Format the way the rows
around them do. Every language was affected including English; German surfaced
it because the placeholder lands at the start of the sentence there. A test now
walks every placeholder-carrying resource string, finds its uses, and fails on
an unformatted one -- verified by putting the defect back and watching it go red.

New preview images. The old set was from 2026-05-08, older than every cycle in
2.0.0, and showed stacked ImGui defaults to anyone browsing the installer. Taken
with screenshot mode on so no character names reach a public repo. The wizard
takes the theme picker's slot.
2026-08-19 23:34:41 +02:00
JonKazama-Hellion 39e2d91288 docs(images): new preview shots, taken on the rebuilt interface
Security Scan (reusable) / Security Scan (push) Successful in 23s
Security / scan (push) Successful in 23s
Build / Build (Release) (push) Successful in 28s
The three in the plugin installer were from 2026-05-08 and showed the plugin as
it looked before any of the window rebuilds -- older than every cycle that
shipped in 2.0.0. Someone browsing the installer saw stacked ImGui defaults.

Taken with screenshot mode on, so the character and world names are replaced
rather than published: the chat shot would otherwise carry a free company
conversation onto a public repo.

The wizard replaces the theme picker in the set. It is the first surface a new
user meets and it now has something to show; the theme picker is reachable from
the settings shot behind it.

Manifest still points at the old file in this commit -- the URLs are checked
against the pushed tree, so the new image has to exist there before anything can
reference it.
2026-08-19 23:33:56 +02:00
JonKazama-Hellion 3309386fbe docs(readme): the front page still described the plugin as it was at v1.1.0
Security Scan (reusable) / Security Scan (push) Successful in 23s
Security / scan (push) Successful in 23s
Build / Build (Release) (push) Successful in 28s
It called the theme engine "a step toward a distinct UI look and feel", which
was true when it was written and stopped being true somewhere around the fourth
window rebuild. It also pointed new readers at `/hellionchat`, a command that
does not exist -- the family is `/hellion` -- and put the wizard at three
profiles when it has had four since May.

The intro says what the plugin is now: a fork by origin, with everything above
the message store rebuilt, and the differences from upstream named as features
rather than as a rewrite plan. The paragraph no longer repeats what the upstream
section further down already explains in more detail.

Added the plugin notice the wizard shows every user. The repo front page is the
other place someone lands first, and it was the only one of the two that said
nothing.

Counted the themes rather than trusting the number I was about to write: ten
built-in palettes, not seven.

Both remaining `/hellionchat` and "24 locales" mentions sit under headings that
say "kept for context" and describe the state at that version. Those stay wrong
on purpose.
2026-08-19 22:52:19 +02:00
JonKazama-Hellion 38c6707970 ci(security): hold API responses in a file instead of piping them onward
Security Scan (reusable) / Security Scan (push) Successful in 25s
Security / scan (push) Successful in 25s
Build / Build (Release) (push) Successful in 28s
Semgrep blocks on gha-curl-pipe-shell, and it is pointing at the publish step
added an hour ago. The rule exists for `curl https://…/install.sh | bash`:
remote content reaching an interpreter. What this actually did was pipe a JSON
response into a python3 -c inline script -- the interpreter and its program both
live in the workflow file, and the server only ever supplied data.

A false positive, then, but the rule cannot see the difference between an
interpreter reading a program from stdin and one reading data, and neither can
the next person to read the step. Responses go to a file and are read from
there. Same shape as the finding suggests, and worth having anyway: a response
that is on disk can be looked at when a call misbehaves, instead of vanishing
into a pipe.

Verified by falsification rather than by a green run: the same ruleset against
the previous revision of this file reports 1 blocking finding, against this one
zero. Without that check a passing scan only proves the rule was not loaded.
2026-08-19 22:49:07 +02:00
JonKazama-Hellion a4c4e15c3b chore(release): 2.0.1
Forge Announce / Post changelog to Hellion Forge (push) Successful in 8s
Security Scan (reusable) / Security Scan (push) Failing after 24s
Security / scan (push) Failing after 24s
Build / Build (Release) (push) Successful in 34s
Release / Build and attach release ZIP (push) Successful in 30s
Same-day hotfix on 2.0.0, nothing user-facing. It exists because the 2.0.0
archive was built before the MessagePack lift, and because the fixed release
workflow needs a tag to prove itself on -- 2.0.0 cannot, since Gitea reads the
workflow from the tagged tree and that tree still holds the broken version.

Not force-moving the 2.0.0 tag: its release object exists with the archive
attached, and someone may already have pulled it.
2026-08-19 22:46:10 +02:00
JonKazama-Hellion 226174bf12 ci(release): publish with curl instead of a go action, and lift MessagePack
Security Scan (reusable) / Security Scan (push) Failing after 23s
Security / scan (push) Failing after 23s
Build / Build (Release) (push) Successful in 30s
The v2.0.0 tag built fine and then died on its last step: gitea.com's
release-action declares `using: go`, the runner has to compile it, and act
cannot -- exec: "go": executable file not found, exit 127, after a green build.
The zip existed and never got attached, so the Discord announcement went out
while the download link pointed at nothing.

This is a known failure. It was diagnosed on another repo in June and the note
from then says in as many words that this repo carries the same pattern and
should migrate before its next release. It did not, and here we are.

The publish step is a plain curl call against the Gitea API now, running in the
job image with curl and python3, independent of go, the action cache, and
whatever @main happens to point at. Idempotent by design: a re-run reuses an
existing release and replaces the asset rather than failing on the duplicate,
which is exactly the state a recovery run finds.

MessagePack moves from the 3.1.4 floor to 3.1.7, which is what the trivy scan
was failing on. The range already allowed it -- NuGet resolves the lower bound
of a range, and trivy reads it the same way, so the floor is the version that
counts. The advisories are recursion depth in Skip and an LZ4 decompression
fault, both reachable only through crafted input; this plugin serialises its own
payloads and reads back its own bytes from a local database, so the practical
exposure is someone who already has write access to the file. Lifted because it
costs nothing and a scan that stays red for a known-harmless reason is how a real
finding gets missed later.
2026-08-19 22:44:55 +02:00
JonKazama-Hellion e316a9b400 Merge branch 'feature/v2.0.0' into main
Security Scan (reusable) / Security Scan (push) Failing after 24s
Security / scan (push) Failing after 24s
Forge Announce / Post changelog to Hellion Forge (push) Successful in 11s
Build / Build (Release) (push) Successful in 33s
Release / Build and attach release ZIP (push) Failing after 30s
2026-08-19 22:36:26 +02:00
JonKazama-Hellion 97d31bb8e4 fix(defaults): the values everyone had set by hand become the defaults
The 2.0.0 reset put every install on the shipped defaults for the first time, and
that exposed which of them had never actually been used. The sidebar was the
loudest: 44 pixels, a width carried over from the v1.2.0 icon-only layout and left
in place long after the sidebar started drawing labels beside those icons. Every
tab name came out clipped. Nobody had noticed in cycles because everyone had
widened it by hand -- 160 in the config this was measured against.

Default 160, and the floor moves from 40 to 130: where a tab name stops being
readable in German, which is the longest of the 25 languages, rather than where
the icons stop fitting. Anyone who wants it slimmer wants the collapsed layout,
and that is a separate width.

Glyph ranges had the same shape of problem with a worse outcome. They were only
ever filled when someone picked a language explicitly, so an install left on
"follow Dalamud" -- the default -- got none at all. That went unnoticed while
configs accumulated ranges over months; a fresh config has none, and a tester on
a Korean, Chinese, Cyrillic or Greek client would have come out of this update
reading boxes. The load path derives them from the Dalamud UI language too now.

The rest are preference defaults taken from a config that has been in daily use
across every one of these cycles: compact density off, title bar off, compact
timestamps on, compact tell tabs on, honorific glow on, 100 messages of tell
history preloaded, inactive opacity 0.75, command help on the right. New tell
tabs open as pop-outs, because the wizard's closing step tells the user to try
/tell and watch exactly that happen.

Two values were deliberately not carried over. SeenPopOutInputHint and
SeenPopOutHeaderHint are not preferences, they are "this user has seen it"
markers -- shipping them as true would mean no new user ever sees the hints that
explain a feature people did not find on their own. The greeted toggle stays off
as well: it is opt-in for people who greet.

Also dropped the light-bulb emoji from the wizard's closing hint in all 25
languages. UI icons come from the icon font here, not from emoji.
2026-08-19 22:34:35 +02:00
JonKazama-Hellion 89c73be71c feat(release): 2.0.0 -- nine cycles ship, and the config starts over
v1.6.0 through v1.15.0 were never published. The whole window layer was being
rewritten from ImGui defaults to custom drawing, and repo.json deliberately kept
its links on v1.5.6 so nobody could update into a half-finished state. That work
lands here in one release.

The config is not migrated, it is replaced. A config carried across nine cycles of
window rebuilds holds values chosen against surfaces that no longer exist, and
starting over is the only way to be sure every install is on the same defaults.
The message database is a separate file and is not touched. The old config is
copied to HellionChat.json.pre-2.0.0.bak first, so rolling back to 1.5.6 stays a
file copy rather than an evening of clicking settings back in.

Config schema 27. The reset runs from the constructor, before LoadAsync seeds the
default tabs, and the self-test now fails if the tab list is empty at /xlperf --
that ordering breaking would leave every user with no tabs and nothing else in the
plugin would notice.

Default layout gains an Emote tab: custom emotes, standard emotes and echo. A
tester asked for it, emotes get lost between system notices otherwise.

Manifest, README, roadmap and the four changelog consumers are on 2.0.0. The
release notes lead with what was fixed rather than what was redrawn -- retroactive
cleanup that could never be applied, a compaction that reported deleting nothing
while deleting everything, pinned tell tabs that came up empty for a session. And
with the one behaviour change users should know about: the channel grid is
authoritative over storage now, so anyone who had unticked channels while the
unknown-channel failsafe was on stores less than they did before.
2026-08-19 22:15:40 +02:00
JonKazama-Hellion 16557213cd chore: comments, second pass -- the task codes the first pass missed
The first sweep matched a character class that swallowed the digit, so a bare
B1 slipped through while B1-2 was caught. Searching the whole A-Z space instead
of guessing prefixes turned up 130-odd more: B0 through B6, C2, C3, D1, H2, M6,
P7, P8, T2, W2, plus GP-04, KB-01, OD-1, PM-1, PM-3, SEC-01, TR-4, TR-7, UI-11,
UI-12, XC-8 and API-3.

Kept deliberately: 41 B4 01 is a byte signature, "N0" a format string,
#L119-L128 a source anchor, LS4/LS6 are linkshells, and A=FF B=0C G=41 R=C2
explains a colour-channel order. Those look like codes and are not.

Also translated the eight German comments left in the theme files and
ImGuiUtil. Seven of them described what a palette does to which channel, which
is worth reading -- just not in a second language in an otherwise English
codebase.
2026-08-19 22:03:12 +02:00
JonKazama-Hellion 5b738e6885 chore: comments say what the code does, not which task produced it
A comment that reads "MUST stay in lockstep with TryGetActiveCrossfade (K8)"
helps nobody outside the plan that used to have a K8 in it, and the plans are
not in this repo. Same for "Spec FR-4", "plan §B.2", "Sub-Task 4.4" and the
F/R/M/A/S round codes scattered through the style engine and the self-tests.

Personal names go too. "tester feedback from Jin (v1.4.7)" and "Flo decision
2026-06-15" carry the reason fine without naming anyone -- the version and the
reason are the parts a reader can act on, and a public repo should not need a
cast list to be read.

The rule applied throughout: keep the why, drop the reference. Version numbers
stay, since those resolve through the changelog. 77 files.

ChunkUtil also carried 281 lines of commented-out code -- an older ToChunks
variant and two helpers with no callers, inherited and never removed. Deleted;
git remembers them.
2026-08-19 21:50:31 +02:00
JonKazama-Hellion 52237fda7e feat(wizard): the profile cards and the welcome page speak the window's language
The cards were the last surface still drawn from ImGui defaults: four emoji on
stock child frames, sized to a fixed 2x2 grid that clipped the longer privacy
descriptions in half the supported languages.

They are tiles in the row language now -- a resting surface, an accent bar down
the left edge when chosen, a held hover over both, tracked caps for the heading.
The emoji are FontAwesome glyphs from the icon font the rest of the plugin
already uses. Each card measures its own height from its text and the pair in a
row takes the taller of the two, inside a scrolling frame, because cutting a
privacy choice off mid-sentence is not a thing this plugin gets to do.

Step three moves onto ToggleSwitch rows and a drawn theme field with a popup
built from PopupRow, using the transient widget overloads throughout: the
Func/Action pair saves on every click, and this step is staged until Finish.

The welcome page is opaque, unlike every other window here. Those are read at a
glance over the game; this one is read once and carries a privacy decision. The
fox sat on a hardcoded off-white rectangle that read as paper taped to the
window -- it is a disc now, tinted from the theme accent and only lightened as
far as the black linework needs, measured rather than set.

Three defects surfaced while doing it, all older than this work:

- The GDPR notice for full history had been translated into 25 languages and
  drawn nowhere since the four-step rewrite dropped it on 2026-05-18. It is on
  the card where the choice is made.
- Two cards claimed to be recommended: the badge sat on casual while the data
  minimisation heading still said "(recommended)" in every language. The suffix
  is gone, and the word it carried became the badge label.
- The wizard had no way back into it at all. /hellion wizard reopens it, and
  OnOpen resets the staged state so a second run cannot commit picks from a
  first one the user never saw.

The welcome text drops the fork framing: Chat 2 and this plugin have diverged
far enough that the codebases no longer line up, so it reads as history in a
muted line rather than as a justification up front. In its place is the notice
that plugins are a grey area in this game and do not belong in public channels.
Channel names in it come from Language.<lang>.resx per language, so the German
build says Sagen/Rufen/Schreien and the Polish one says Say/Yell/Shout, which is
what a Polish player actually sees on an English client.
2026-08-19 21:50:21 +02:00
JonKazama-Hellion 5958bceb1c feat(wizard): the chrome speaks the window's language (block A of v1.15.0)
The wizard is the first thing a tester ever sees and it was the last surface
still drawn in ImGui defaults -- stock buttons under a hardcoded forge bronze
that ignored the active theme entirely, since v1.5.2.

Block A is the frame: the settings backdrop at full strength, pagination dots on
the contrast-checked theme accent (current step filled, the rest rings, so the
position reads by shape), step-3 section headers in the tracked-caps-and-fading-
rule language every finished window uses, the primary action as the chamfered
accent pill, and back/skip as ghost links. The selected profile card's border
and the step-4 accents follow the theme now too.

Still open, deliberately: block B gives the profile cards their real shape --
including replacing the emoji icons, which have stood against the global
no-emoji-as-UI-icon rule since the cards were built -- and block C moves the
step-3 checkboxes onto ToggleSwitch rows and the theme list onto PopupRow.
2026-08-19 19:44:39 +02:00
JonKazama-Hellion 6fadbb1659 Merge branch 'feature/v1.14.0' into main
The input row cycle: two ghost buttons and a menu where five filled defaults
sat, a field with its own surface and focus rail, popups built from the
sidebar's row shape, a softened seam to the conversation, and hover fades at a
human pace. Plus the style lab and the preflight guard for the RGBA/ABGR trap.

Local state only. repo.json stays on 1.5.6.0.

Note on shape: these commits were made directly on main by mistake and were
re-homed onto feature/v1.14.0 before this merge, so the branch-per-cycle rule
holds in the history even where it slipped in the moment.
2026-08-19 19:35:51 +02:00
JonKazama-Hellion dcc8ff1867 chore(release): close the v1.14.0 cycle
Version to 1.14.0 in the csproj, changelog and roadmap for the local state. Not
published: repo.json stays on 1.5.6.0, links untouched.

The changelog leads with what the row became and is honest about how it got
there: every style decision in this cycle was made by looking at variants in the
lab, in-game, against the live theme -- and the two recurring traps of the day
(the RGBA/ABGR contrast swap, popups that do not size to their content) each
left a guard behind rather than just a fix.

Smoke-tested continuously by Flo through the evening rather than at a single
gate: the contrast bug, the clipped menu, the hover speed and the seam hardness
were all his catches, live, and each is named in the log where it was fixed.
2026-08-19 19:35:35 +02:00
JonKazama-Hellion 9e62ed762d fix(style): slower still -- the fade takes a third of a second now
The halved rates were still judged much too fast, so: 3/s in, 2/s out. Rise in
roughly 330ms, settle in 500ms. The textbook says hover fades live around 150ms;
the textbook does not play this game, and the person who does gets the vote.

Timing guard moved with it.
2026-08-19 19:29:01 +02:00
JonKazama-Hellion eeffb5bc6b fix(style): the hover fade ran at light speed, and stopped dead
Tester feedback via Flo, aimed at the sidebar tabs but true everywhere: 14/s in
means a full fade in seventy milliseconds, which is five frames -- fast enough
to read as a flicker rather than a fade. Halved to 6.5/s in and 4/s out, which
puts the rise around 150ms and the settle around 250ms, where UI fades usually
live.

And the curve was linear: one speed the whole way, then a dead stop. Consumers
now get a smoothstep over the linear state -- soft start, soft landing -- while
the state itself stays linear, because the evict rule and the advance step are
written against it. Every hover in the plugin inherits both changes through the
one Query call, so the sidebar, the popups, the ghost buttons and the message
rows all breathe at the same pace.

The timing test now guards the other direction: it fails if anyone drifts the
rate back toward light speed.
2026-08-19 19:26:47 +02:00
JonKazama-Hellion 12a445e08f feat(sidebar): soften the seam and let the active tab reach its content
Tester feedback, relayed by Flo: the transition from the tab list to the chat
field is too hard, and the tabs could present themselves better. Three causes,
three changes, no structural touch -- tabs stay tabs, per the standing decision.

The full-width border line under every row was a ladder of hard cuts. It is a
fading rule now, starting past the icon column and dissolving before the right
edge -- the same shape the section headers have used since v1.11.0, at about
half the opacity.

The gap between the sidebar group and the message area was a bare strip of
window background with a hard edge on both sides. A faint surface wash fades
across it toward the messages, turning the cut into a seam.

And the selected tab bridges that gap: its active fill extends across the
spacing so it touches the conversation it selects -- the classic tab metaphor,
attached instead of adjacent. The bridge is a RowStyle knob (default zero), so
sidebar rows opt in and nothing else inherits it. Hover fills picked up the
standard three-pixel rounding on the way.
2026-08-19 19:20:22 +02:00
JonKazama-Hellion 8a9692a71d fix(chat): size the popups from their rows, not the rows from a guess
An ImGui popup does not grow for draw-list content, so both new popups carried a
fixed minimum width -- and German outran it within a day. The menu clipped
Schnellauswahl and Chat ausblenden mid-word; the channel picker would have done
the same to Freie Gesellschaft on a narrow theme font.

PopupRow gets a CalcWidth that measures label plus icon plus padding under the
faces that will draw them, and both popups take the widest visible entry as
their width. Locale-proof by construction: whatever language writes the longest
string sets the size.
2026-08-19 19:13:30 +02:00
JonKazama-Hellion 3e46600fc3 fix(style): the popup text fed RGBA into the contrast helper -- and a guard so this stops recurring
Fifth and sixth occurrences of the same defect in one day, this time in PopupRow
and three spots in the lab. The menu entries and the channel picker were
unreadable at rest on the green theme and only became legible on hover, because
the hover lerp pulls toward a correctly converted accent -- which is exactly the
symptom the tester reported.

The shape of the mistake is always identical: a raw ThemeColors member (RGBA)
handed to EnsureContrast (ABGR). The compiler cannot see it, both layouts are
uint, and a stray extra RgbaToAbgr around the call makes the result look
plausible while measuring a contrast between two colours that are never on
screen.

So this commit is mostly the guard. preflight Block G runs
scripts/verify-colour-channels.sh, which flags any raw theme member in either
argument of EnsureContrast across the UI tree. Falsified before trusting: broken
deliberately, it goes red; and on its very first real run it caught three
offenders in the lab that a hand-rolled grep had missed minutes earlier.
2026-08-19 19:09:22 +02:00
JonKazama-Hellion d7a308b522 feat(style): option three across the board, every colour contrast-bound
Flo picked the third variant in all four lab sections, with one warning attached:
bind the glyph and text colours to the contrast helper or the theme, or they
drown. The warning was well aimed -- the ghost buttons from the previous commit
were feeding RGBA into EnsureContrast, the same channel-order mistake the header
made this morning, and the pill text was raw TextPrimary on an accent fill with
no check at all. Every colour in the row now goes through EnsureContrast against
the surface it actually lands on.

What changed shape:

The icon buttons glow. Flat at rest, and on hover a soft fill with an accent
glow border rising on the held hover value -- DrawGlowBorder's first caller ever.
The lab version of that glow had its alpha in the wrong byte (DrawGlowBorder
reads RGBA, ApplyAlpha writes ABGR), so what Flo approved was a full-alpha glow
with a dimmed red channel. Fixed in both places, with the alpha byte set by hand.

The channel pill is chamfered, the segmented control's corner language, with the
white depth gradient kept. The rounded Pill widget stays untouched for the
status bar.

The channel header trades its fading rule for a tenth-opacity accent wash from
the top edge. Colour as atmosphere rather than as a box -- at this strength it
survives the violet themes that killed the filled bar in v1.11.0.

The lab stays in permanently, by Flo's call: a dev playground for seeing ideas
in-game against the live theme. Its radios now default to what shipped, so the
window doubles as a record of which variant won.
2026-08-19 19:04:05 +02:00
JonKazama-Hellion 6bdfecb1df feat(chat): the input row learns the window's own language
Five filled plates become two ghost buttons and a menu. The plates were ImGui
defaults sitting between a drawn pill and a drawn status bar -- three shape
languages in the one row a user works in, which is what the tester's screenshot
made obvious. The ghosts follow the sidebar's icon buttons: nothing at rest, a
held hover fill, the glyph lifting toward the accent.

Symbols stay outside the menu because they are used mid-sentence. Theme,
settings, screenshot and hide move in; the screenshot toggle was allowed in only
because its state moved to the status bar first, as an accent pill that shows
while the mode is on. A privacy state behind a closed menu answers nothing.

The input field paints its own rounded surface and hands ImGui a transparent
frame, so the widget draws only text and caret -- the Boutique.Inputs technique
from Character Select+, no rebuild of the widget itself. Focus is a two-pixel
accent rail on the left edge: the same mark the rows, the popups and the message
list already use for "this is where you are".

The channel pill gets the CS+ treatment, a faint white gradient and a one-pixel
light along the top edge. White over the fill rather than a second hue, so it
reads as depth in every palette.

And the popups that open from the row are made of PopupRow now -- the sidebar
row's shape, which is also exactly what CS+ draws for its own popup entries. The
channel picker was the reported case: a drawn pill opening a list of naked
selectables, the style breaking mid-click.

A hundred-odd pixels of button reserve go back to the input field.
2026-08-19 18:30:15 +02:00
JonKazama-Hellion df6296024b feat(style): a lab window for the input-row decision
Four elements, three variants each, drawn side by side in real ImGui against the
live theme. Reachable with /hellion lab.

The alternative was drawing mockups, and mockups are what sent this cycle wrong
once already -- they predate the settings window learning that structure is
typography and only controls get a fill. A picture also cannot show the part that
matters most here: switching themes switches which variant works.

Everything it draws comes from helpers that were already in DrawListExtensions
and had almost no callers. DrawSlipPolygon and DrawVerticalGradient had one
between them, in SegmentedControl. DrawGlowBorder had none at all.

Temporary, and deliberately not behind DEBUG: the decision happens in the build
Flo runs. It comes out once the variants are picked.
2026-08-19 18:22:34 +02:00
JonKazama-Hellion 6449a51daa fix(chat): the channel header had a plate the settings window gave up weeks ago
The mockup draws this band as a filled surface, and I built it that way. The
settings window used to draw its section headings the same way -- and dropped it
in v1.11.0, with the reason written into SectionHeader: a fill reads fine against
blue themes and vanishes against violet ones, because its only distinction from
its surroundings is hue. Tracking is shape, and shape survives every palette.

Side by side with yesterday's build the difference was obvious: the settings
window sets VERHALTEN and TASTENKÜRZEL as tracked caps with a rule that fades
out, while the chat window right next to it carried a lit bar. One window was
three weeks ahead of the other.

So the plate is gone and a fading rule runs between the channel name and the
world, stopping short of it. Same shape the settings headings have had since
ced7ea0.

Worth writing down because the mockups are where this came from, and they are
from before that lesson. They are the starting point of the style track, not its
target -- the target is how far ImGui can be pushed, and the plugin has been past
these drawings since v1.11.0.
2026-08-19 18:08:37 +02:00
JonKazama-Hellion 0abbbc8f8a docs(roadmap): the sidebar comes off the list, the input bar goes on
Both reasons the channel-rows idea existed are gone. It was written when the
sidebar was flat and unstyled; v1.10.0 gave it row surfaces and it already groups
pinned and auto-tell tabs under headings. What was left was a change to how the
plugin is operated rather than how it looks -- and tabs are what users have
learned to use.

Next two are the input bar and the first-run wizard, the last surfaces still
drawn in ImGui defaults.
2026-08-19 17:48:39 +02:00
JonKazama-Hellion de094a8d4f Merge branch 'feature/v1.13.0' into main
Typography cycle. Named type roles instead of one size, a channel header above
the conversation, timestamps in a column of their own, rows with a surface, and
local plus server time in the status bar.

The heaviest finding was not typographic. Screenshot mode reached one of the four
surfaces that draw a tab name, and an auto-tell tab is named Player@World -- so a
picture of the default view named the conversation partner while every message
below it was anonymised. All four share one rule now.

Config version 26. Local state only; repo.json stays on 1.5.6.0.
2026-08-19 17:40:26 +02:00
JonKazama-Hellion b57ca23b9f Merge branch 'feature/v1.12.0' into main
Reconnection cycle. Export, the tab editor, database maintenance and pinning were
unreachable after the v1.6.0 window rebuild; all four are back, the settings
window is translated into 25 languages, and the channel grid decides what gets
stored.

Local state only. repo.json stays on 1.5.6.0 and the download links are
untouched.
2026-08-19 17:40:20 +02:00
JonKazama-Hellion 64f48b1131 chore(release): close the v1.13.0 cycle
Version to 1.13.0 in the csproj, with the changelog and roadmap entries for the
local state. Not published: the public release stays at v1.5.6, repo.json keeps
its 1.5.6.0 manifest and all three download links are untouched.

The changelog leads with the screenshot-mode gap rather than with the typography,
because that is the part that changes what a user's own screenshots contain. An
auto-tell tab is named "Player@World", and three of the four surfaces that draw a
tab name had no rule about it -- so a picture of the default view named the
conversation partner while every message below it was anonymised. Anyone who has
shared a screenshot from an older build should know that.

Config version 26 is in there for the same reason. Its migration marks existing
tell tabs as partner-named, and it says plainly what it cannot do: a tab promoted
to permanent before this version keeps its name and loses every marker, so
nothing in the stored data says where that name came from.

Known issues carry the honest tail: the header recomputes its widths every frame
instead of on the status bar's tick, and all three font handles now rasterise the
full glyph range -- the cost of letting the channel name use the smaller face
without breaking on an umlaut.

The migration self-test asserts what v26 actually does now, rather than only that
the version number moved.
2026-08-19 17:34:49 +02:00
JonKazama-Hellion 3b5001e616 feat(chat): local and server time side by side, and a quieter header
Both clocks in the status bar, in the game's own LT/ST notation. Anyone agreeing
on a time across regions reads them off one line instead of doing the arithmetic
in their head.

Server time is not computed here and must not be. Framework.GetServerTime() hands
it over, so the plugin follows whatever Square Enix does with it -- a local UTC
conversion would be right today and quietly wrong the day that stops holding.
Umbra reads it the same way. The slot drops out on its own like every other one,
and it is empty while logged out, because then there is no server to read a clock
off.

The header gives up its clock in exchange. With both times in the status bar it
would have been the third copy of the same number on one screen, and the header's
job is to answer where you are, not what time it is.

Its title also moves down to the meta size. Tracked caps at body size read like a
headline, and the header is meant to answer a question rather than announce one.
That only works because the meta face now carries the full glyph range: it was
built with an ASCII-sized one on the assumption it would only ever draw clocks
and world names, and a single umlaut in a tab name would have broken it. All
three delegate handles rasterise the full set now -- the honest cost of the
change, and the reason the size distinction is worth having at all.

Two things fell out along the way. The detail no longer needs a flag saying "draw
me in the body face", because there is no glyph the meta face cannot reach. And a
culture-pinning test lost its subject when the clock left, so it asserted nothing
and is gone rather than repaired.
2026-08-19 17:29:20 +02:00
JonKazama-Hellion 439c919d77 feat(chat): a button for screenshot mode, where it can actually be found
It has only ever lived in the right-click menu on a player name. For a privacy
feature that is the same as not existing -- reported as missing by a tester who
has been running the plugin for months and never found it.

Now a camera in the input row, next to hide-window, and lit in the accent colour
while active. A mode whose state you cannot see is worse than no mode: the whole
point is knowing whether the names on your screen are real before you press the
screenshot key.

The button reserve goes from 130 to 156 to fit it. No new string -- the context
menu's label is already translated into all 25 languages and says exactly what
the button does.
2026-08-19 17:13:06 +02:00
JonKazama-Hellion e2b6e7a992 fix(chat): the header measured contrast against the wrong colour space
EnsureContrast works in ABGR. I handed it the theme's RGBA on both arguments, so
it swapped red and blue in the foreground and in the background, measured a
contrast between two colours that were never on screen, and returned a result in
the wrong order -- which then went through RgbaToAbgr a second time.

On a violet surface with a teal accent that came out as dark bordeaux on dark
violet: the exact unreadable pairing the call was there to prevent. Reported from
a real screenshot, not from a test, because nothing here is testable without a
draw frame.

Every existing caller in the codebase passes ABGR -- SettingsPalette hands over
_palette.Abgr(...), SegmentedControl uses fields literally named LabelAbgr and
TrackAbgr. Mine were the only three that did not, and all three were written in
this cycle.
2026-08-19 17:09:05 +02:00
JonKazama-Hellion 80ec7450c8 feat(chat): stop repeating the same minute on every line
The comparison value comes from the message data, not from a variable carried
between rows. In 1.5.6 the loop walked every message and skipped invisible ones
with a dummy, so what it remembered was the last *visible* stamp. The virtualised
list only iterates the visible window, so the row above that window was never
drawn at all -- a carried variable would hold whatever was on screen before the
last scroll, and the first stamp after every jump would be wrong.

No predecessor means draw. Scrolling into the middle of a log would otherwise
swallow the only stamp on screen.

Both draw paths now pass an index; the linear one was a foreach and had none.

The setting is on by default and existed with translations in twenty-three
languages -- Catalan and Italian had kept the English string, so those two are
done now. It needs no fingerprint entry: the column stays reserved when the stamp
is suppressed, so hiding one changes no row's height.
2026-08-19 12:07:39 +02:00
JonKazama-Hellion b63e1eda9b fix(privacy): one rule for tab names, applied to all four surfaces
The header was the only place that knew a tab name can be a person. The sidebar,
the tab strip and a pop-out's window title drew the same "Player@World" string
untouched, so a screenshot of the default view still named the partner while the
messages underneath were anonymised. Guarding one surface out of four guards
nobody.

The rule sits in one place now and all four read it. Names are replaced rather
than blanked: a nameless tab in a strip of tabs is worse to use than a
placeholder, and the sidebar has no room to explain itself. The salt is drawn
fresh on every plugin load, the same reasoning the message path uses -- a stable
label would let two screenshots taken weeks apart be tied together.

The tab strip resolves once and both measures and draws that value. Measuring one
string and drawing another would have sized every tab wrong the moment the mode
came on, which is the kind of thing that looks like a layout bug and gets fixed
in the wrong place.
2026-08-19 12:04:55 +02:00
JonKazama-Hellion 1604186aa1 test(style): pin the type scale table, and mark three mirrors
The arithmetic had tests from the first commit; the table in front of it did not.
Factors is indexed by the enum, so a role inserted in the middle shifts every
factor below it -- and each one still resolves to a plausible size, which is
exactly why nothing would have failed.

Three files were missing their TEST-MIRROR marker despite having mirrors. The
marker is how the drift check finds them.
2026-08-19 12:01:31 +02:00
JonKazama-Hellion 8fea9113b9 fix(privacy): the screenshot guard was reading a field that gets wiped on purpose
This morning's fix hung on TellTarget, and TellTarget is routing state that the
codebase clears deliberately. StripTellBindingOnPromote sets IsTempTab false,
empties TellTarget, and keeps the name -- so a promoted tell tab is called
"Player@World" permanently while carrying neither marker, and falls through both
possible checks. That state survives restarts. A pinned tab whose binding did not
survive a save is the same hole with a different cause; the auto-tell service
logs that case as expected and repairs around it.

The flag is set where the name is built from a partner and is not cleared by
promotion. Renaming clears it, because at that point the user typed it.

Config v26 carries it backwards for tabs that already exist: anything still
holding a tell binding or the temp flag got its name from a partner. Tabs
promoted before this version cannot be recovered -- nothing in the stored data
says where their name came from -- and renaming one has the same effect anyway.

Two more things the header was giving away. Its icon for an auto-tell tab is
derived from the partner and stable across sessions, which is three bits of
linkable information on a picture meant to be shareable; the message path
re-salts its name hashes on every load precisely to avoid that, so screenshot
mode now falls back to a plain envelope. And a world name that is not ASCII --
the CN and KR clients have those, and we ship translations for both -- was being
drawn in the meta face, which carries ASCII and a middle dot. It would have come
out as question marks, the same defect the split was built to prevent.

Plus two that are not privacy: the header had no FontsReady gate, alone among
the drawing components, so its band height and baseline offset were wrong in
exactly the frames this cycle made more common. And a long tab name ran past the
band and got cut mid-glyph at the window edge; it fits now, the way the honorific
header already did it.
2026-08-19 12:00:16 +02:00
JonKazama-Hellion 0399b68d8c fix(settings): let the preview show what the log shows
The preview was four flat lines of text on a plain field. After this cycle the
real log has a channel header above it, a fixed timestamp column, and system
messages in italics -- so the preview had quietly become a picture of a window
that no longer exists. That is the same defect as a widget with no call site,
just pointing the other way: something on screen that stopped tracking what it
describes.

The reserved band grew with it. It is a fixed height that the sidebar mock also
divides by, so adding a row inside without raising it would have pushed the last
message out of the space -- the recurring drawing-into-unreserved-space mistake
this project keeps stepping on.

Preview stamps are fixed rather than live. A clock ticking inside a settings
panel pulls the eye away from the setting being changed.
2026-08-19 11:50:19 +02:00
JonKazama-Hellion 63d1b34b00 feat(chat): two densities that actually look different
Card density puts the sender on its own line with the body indented onto the text
column beneath it, and six pixels of air after each one. That air is what makes a
card read as a card, and it goes through the measured row height so the clipper
plans against it rather than around it.

System messages go italic in both densities. Nobody said them -- it is the game
talking -- and italics carry that in every palette. Colour would have been the
obvious alternative and is the wrong tool twice over: the rule this cycle runs on
says typography solves what typography can, and the channel colours already in
those chunks come from the game and are not ours to dim.

The italic face falls back to the game's own italic rather than to upright text
when the custom one is switched off, so the distinction survives either setting.
2026-08-19 11:48:46 +02:00
JonKazama-Hellion 81e4c9367a feat(chat): give each row a surface to sit on
A wash from the left at a tenth opacity, a two-pixel accent bar on the edge, both
fading in and out on the held hover value rather than snapping.

Two draw paths, because the height arrives at two different times. On a normal
frame the cached height is already correct -- a chat message does not change
height after its first measurement -- so the surface goes down before the text
and costs nothing. On the frame after the cache is dropped no row knows its
height yet, and that is the only time the draw-channel detour is needed. Without
it the entire list would flash bare for one frame after every window resize,
which is not rare: width and display scale are both in the fingerprint.

The gradient and the rounding cannot be one call. AddRectFilledMultiColor writes
four fixed vertices and takes no rounding parameter, so the rounded base goes
down first with the gradient inside it. At two pixels the bar has no visible
corners at all and needs neither.
2026-08-19 11:47:46 +02:00
JonKazama-Hellion ba16ab59e3 feat(style): a scope for drawing behind text that has not been measured yet
Needed on exactly one frame: the one after the height cache is dropped, when no
row knows its own height yet. Every other frame the cached height is already
right -- a chat message does not change height after its first measurement -- and
the caller paints the fill directly without coming near this.

Modelled on LightlessSync's SettingsCardScope, which had already worked out the
two things that make draw channels dangerous. Nesting a splitter into itself
asserts, and Dalamud does not compile asserts out, so the user gets an error
dialog rather than a glitch -- hence the depth count. And a forgotten merge is
not a dropped frame but a permanent one: the commands stay in the channel buffers
and never reach the draw list, then the next frame's split walks into the assert.
Hence the finally, by way of the struct's Dispose.

Fill switches to the background channel and switches straight back, so a caller
cannot leave the channel hanging even by returning early.
2026-08-19 11:46:40 +02:00
JonKazama-Hellion 611dd368cb feat(chat): give the timestamp its own column, and the show-timestamps box its effect back
The stamp used to be text at the head of the line with two spaces after it, so
every sender name started wherever the previous stamp happened to end. It sits in
a fixed column now, measured once per draw from the widest shape the current
format can produce, and the names line up.

The column stays reserved when the stamp is hidden. Collapsing it would make a
per-tab switch change every row height in that tab, and the height cache would
have to carry wrap positions rather than just the format.

tab.DisplayTimestamp has a reader again. It was in 1.5.6 at two call sites and
lost both when cf4705e retired the old chat window; the tab editor has been
writing a setting nobody read since. Same class of defect the last cycle spent
itself on, found in passing here.

The sender draws in the heavier face and the stamp in the smaller one, both
dropped onto the body baseline -- ImGui aligns a row by its top edge, so without
that the stamp would hang. All three faces follow the same FontsEnabled or
UseHellionFont pair every other push site follows; with the game font selected
there is no heavier or smaller variant and the row falls back to one face.

Card density gets the two-line treatment only where there is a sender. A system
message has none, so a header row would be a stamp alone on a line -- an empty
gesture. Those stay single-line in both densities.
2026-08-19 11:46:01 +02:00
JonKazama-Hellion a841942b41 fix(layout): the clock format and the per-tab timestamp switch move row heights
Two more axes the height cache never knew about, and the second one is not even
wired up yet -- it is about to be.

Use24HourClock changes the stamp from 15:45 to 3:45 PM. The stamp sits at the
head of the line with SameLine(0,0), so the wrap width every following word is
measured against shrinks. Rows that wrap near that boundary get a different
height, and nothing dropped the cache.

DisplayTimestamp is per tab, which is why BuildLayoutFingerprint now takes the
tab. It only ever read Plugin.Config before -- the per-tab part of this system is
the gate, one per tab, comparing fingerprints that knew nothing about tabs. The
switch is dead today and gets its reader in the next commit; the axis goes in
first so the cache is right the moment it starts doing something.

Both are toggles, so they sit in the discrete half and skip the settle window.
2026-08-19 11:44:30 +02:00
JonKazama-Hellion ad7421fbed feat(chat): the sample the timestamp column measures against
Eights rather than zeroes. In most faces 8 is the widest digit, and a column
measured from 00:00 gets undercut by a 10:38 -- which would shove the name column
right on exactly that row, the misalignment the column exists to remove.

Two samples because the twelve-hour form is wider. That difference is why
Use24HourClock has to enter the layout fingerprint: switching it moves every wrap
position after the stamp, and the height cache never knew.
2026-08-19 11:43:38 +02:00
JonKazama-Hellion 56a9f3f474 fix(privacy): the header gave away what the log was hiding
Screenshot mode anonymises sender names in the message list. The channel header
I added yesterday sat above that list and showed two things it should not.

The home world, on the right. It narrows a player down almost as far as the
character name does, and the mode exists so a picture can be shared.

Worse, the tab name on the left. AutoTellTabsService builds a tell tab's name as
"Player@World", so a tell conversation had the partner's name and world set in
tracked caps directly above a log where every message had been anonymised. The
one place a reader looks first was the one place still naming them.

The name is suppressed only where it actually names someone -- a tab with a tell
target set. General or Trade stay readable, because they identify nobody, and a
self-named tab is the user's own text.

Found by asking what the new surface shows rather than by a test failing. Nothing
here was failing.
2026-08-19 11:42:13 +02:00
JonKazama-Hellion e810d2479d refactor(style): drop the type role that could never be pushed
TypeRole.Header had no call site and could not get one. The channel header is set
apart by small caps and tracking, not by size, so the role resolved to exactly
Body -- a value that would sit in the enum being equal to another value forever.

That is the precise thing this style track exists to prevent. Five widgets shipped
once with no call site at all, and the rule that came out of it says no piece
lands without one in the same pass. Writing a caller just to satisfy the rule
would have been worse than the rule.

Also cleans two comments the pop-out rewrite left pointing at things that are
gone: a close button that lived on the removed title row, and a method
description with no method under it.
2026-08-19 10:22:25 +02:00
JonKazama-Hellion dfc0cda806 fix(chat): four things the header review found, all of them visible
The self-test was the worst of them, because it is the only tool that makes block
A judgeable at all and it destroyed itself on use. It returned Fail while the
atlas was not ready, and its own weight buttons trigger a rebuild -- which is
asynchronous, not synchronous as the comment claimed. Click a weight, watch the
step go red. It waits now, like the two existing steps that had already worked
this out.

The translated stand-in was drawn in the meta face, whose glyph range is ASCII
plus a middle dot. Fifteen of the twenty-five translations reach outside that, so
"not logged in" would have rendered as a row of question marks in Japanese,
Russian, Korean, Greek and eleven others -- and the measured width would have
been the width of the question marks, so the right edge would have drifted too.
The plan said to keep it on the body face and the comment in FontManager says so
as well; the code simply did not. The detail is two parts now rather than one
string, and each part is measured under the face that draws it.

The header was the only place in the UI pushing RegularFont directly, without the
FontsEnabled-or-UseHellionFont check every other push site makes. With both
toggles off the window draws in AXIS and the header would have drawn in
Inter-Light, at a different size, in a band measured against a third one.

And the icon sat on the text baseline. FontAwesome is a fixed-width handle built
at Dalamud's own size and does not follow the plugin's font setting, so at any
other body size it hangs. The sidebar already knew this and centres against the
row; the header does the same now.

Two smaller ones came along: the minimum-height threshold was compared unscaled,
which would have dissolved it at higher display scales, and the height passed
into that check included the input row -- so "is there still room to read" was
measuring the wrong thing. Both callers now say what sits below them.
2026-08-19 10:21:03 +02:00
JonKazama-Hellion 100290ea4d feat(chat): put the channel header above both windows
Drawn before the scroll child in each, so it stays put while the log moves. The
child's height is deliberately left alone: it is given as a negative value, and
ImGui resolves those against the space still available from the current cursor --
which the header has already reduced. Subtracting it a second time would have
opened a gap of exactly the header's height above the input row, in both windows.

Where the name shows follows one rule: never twice on the same screen. The
sidebar layout is the only place nothing else carries it, so that is the only
place the header says it. The top-tab strip carries it, and a pop-out with its
title bar on carries it in the title.

The pop-out's plain title row is gone, replaced by the header. The comment it
left behind is worth keeping in mind -- an earlier header row was removed exactly
because it repeated the tab name one line below the title bar. That warning is
now the rule rather than a reason to have no header at all.

The trailing detail is the home world and the clock, and the clock follows the
same Use24HourClock setting the message timestamps do. Two clock formats in one
window, with the header sitting directly above a column of timestamps, would be a
defect rather than a preference. Culture is pinned for the same reason it is
pinned in the message list.
2026-08-19 09:58:29 +02:00
JonKazama-Hellion 74f9ff7f16 feat(chat): a header that says which channel you are in
Small caps with wide tracking, not a smaller size. The mockup asks for one pixel
below body text, and one pixel would have cost a whole additional font handle at
full glyph range -- tab names are free user input and can be CJK. Tracking reads
the same in every palette and costs nothing, which is the same argument that
settled the section headings in the settings window.

Only the world and the clock use the meta face. Its glyph range is ASCII plus a
middle dot, so anything that gets translated has to stay on the body face.

Two things it will not do. It drops the tab name where one is already on screen:
a pop-out with its title bar on carries the name in the title, and the top-tab
strip carries it too. Repeating it one line below is the exact defect that got an
earlier header row removed, and the comment left behind at that removal is what
made this rule. And it disappears entirely below a minimum message-area height --
the window minimum is 260px, already shared with the honorific header, the input
row and the status bar, and all of it scales together. A header that leaves two
readable lines is worse than no header.

Both decisions are arithmetic and sit in ChannelHeaderLayout with tests. The
gallery gets an entry despite the header needing a tab and the font handles,
because that window exists precisely because pieces once shipped without a call
site.
2026-08-19 09:55:13 +02:00
JonKazama-Hellion 0551116a0c refactor(sidebar): let the channel header resolve the same icon
Visibility only. The header has to show the icon the sidebar row shows, and the
lookup table alone would not do it: it only answers for a tab with an explicitly
chosen icon, and the default is none. Most tabs reach their icon through the
derivation this method wraps.
2026-08-19 09:52:49 +02:00
JonKazama-Hellion 64f7d9b975 style: let csharpier reflow the widened tuples
Formatting only. The five-element fingerprint tuple and its field declaration ran
past the line limit, and preflight block E is stricter than the check I had been
running per task -- it caught what the narrower filter did not.
2026-08-19 09:51:53 +02:00
JonKazama-Hellion 81456c981b test(selftest): show what each type role actually resolves to
Block A ends with no call site in the message list -- that arrives in block C --
so without this step there would be nothing to look at and two helpers with no
caller at all.

It draws rather than asserts, because asserting proves the wrong thing here.
SimplePushedFont pushes nothing at all when a handle is not ready, silently, and
the text then renders in whatever face was already active. A step that compares
two numbers and reports Pass would sail straight past that. So this one puts a
timestamp, a sender and a body line next to each other and lets them be looked
at, with expected-against-actual printed underneath.

The three weight buttons exist because the alternative was three builds and a
plugin restart between each, and nobody compares a typeface across a restart.
RebuildDelegateFonts is synchronous on this thread, so the sample row picks up
the new rasterisation on the next frame.
2026-08-19 09:50:56 +02:00
JonKazama-Hellion 0916f8d1fb feat(style): put mixed sizes on a shared baseline
ImGui lines items up by their top edge. ItemSize only shifts anything when
CurrLineTextBaseOffset is non-zero, and that stays zero unless
AlignTextToFramePadding ran -- so a meta timestamp beside a body-sized name would
sit flush at the top and float above the baseline.

The correction is the difference of the two ascents, scaled. The scaling looks
like it is applied twice and is not: Dalamud rasterises at SizePx * GlobalScale
and then divides the metrics back down, so ImFont.Ascent comes out logical.
Drawing multiplies it up again. The comment says so, because the first reviewer
to see this file read it the other way.

No call site yet -- the self-test in the next commit takes it, and the message
list takes it in block C.
2026-08-19 09:49:21 +02:00
JonKazama-Hellion 147034bda5 fix(layout): four axes that could always stale the cache, and the new roles
The height cache keys on a fingerprint of everything that can change a row's
height. Four things that can were never in it:

- ItalicFontV2.SizePt. ChunkRenderer pushes the italic face mid-row for emphasis,
  so there have been mixed sizes in a single line all along -- nobody called it
  that. Changing only the italic size moved every wrapped row and left the cache
  untouched.
- ItalicEnabled, which swaps between ItalicFont at its own size and AxisItalic at
  the base size.
- FontsEnabled and UseHellionFont, which swap the face outright. This pair is the
  quiet one: both size fields default to 12.75f, so the fingerprint did not move
  at all while the glyph widths underneath it did.

On top of those, the two new role sizes. They follow the base arithmetically, but
the resolved value is what belongs in the fingerprint -- a theme override moves
the base without moving any factor.

The three toggles go in the discrete half so they bypass the settle window, the
same way density already does. The sizes are sliders and wait it out.

Falsified rather than assumed: dropping FontsEnabled back out of Discrete turns
the new test red, so it is measuring the axis and not just passing.
2026-08-19 09:48:35 +02:00
JonKazama-Hellion 34e343d8f2 feat(fonts): a handle for the sender and one for the meta line
Two roles need a face of their own, and they need it for opposite reasons.

The sender is meant to carry weight. The mockup says 600, and there is no bold
face anywhere in the plugin -- the bundled file is Inter-Light and the game's
Axis is a single weight. So the weight comes from rasterising the same outline
denser, via RasterizerMultiply. That only works on the delegate path: with both
font toggles off the game font handle draws and has no such knob, and the sender
falls back to leaning on channel colour alone. Deliberate limitation, not an
oversight.

The meta face goes the other way: smaller, and on a glyph range of about eighty
entries instead of the full set. Timestamps and world names are Latin in every
client FFXIV ships, so ASCII plus the middle dot covers what this face will ever
be asked to draw. A full range would have rasterised the whole CJK block a second
time for nothing. Anything translated stays on the body face.

Two things in the rebuild path had to change with them. The handles now go up
inside a SuppressAutoRebuild block -- without it, one size change meant four
separate atlas rebuilds instead of one. And FontsReady checks both new handles
unconditionally, unlike ItalicFont which is allowed to be null: a handle that is
not ready makes SimplePushedFont push nothing at all, silently, and the first
frame after a rebuild would measure the wrong face and write those heights into
the row cache.

Both font self-tests were extended to match. A handle nobody asserts is a handle
that can go missing for a release without anyone noticing.
2026-08-19 09:46:34 +02:00
JonKazama-Hellion 6d2bb95528 feat(style): name the four type roles
Body, Sender, Header, Meta. Three of them share the base size, which looks like
an oversight and is not: the sender is set apart by weight and the header by
small caps with wide tracking. Neither of those is a size, and solving them with
size instead would turn the log into a ransom note. Only meta steps down, because
it is meant to be skipped over rather than read.

Factors sit in a static array rather than as consts. The master spec puts
typography under theme control, and ThemeTypography is already the declared
extension point for it -- a const would wall that off before anyone gets there.

No caller yet. FontManager takes the first one in the next commit; that is the
one place in this cycle where a piece lands before its call site, and it closes
inside the same block.
2026-08-19 09:44:31 +02:00
JonKazama-Hellion 58830aecec feat(style): the arithmetic behind a type scale
Quarter-point rounding, not whole points. The base size is 12.75pt, so rounding
a derived role to whole points would move it further than the step between two
adjacent base sizes -- the scale would quantise away the difference it exists to
express.

The floor is what keeps the meta role legible when someone runs a small base
size; below about seven points a timestamp stops being readable at any display
scale.
2026-08-19 09:44:05 +02:00
JonKazama-Hellion fc67c0852a fix(text): give the wrap calculation the scale imgui actually asks for
CalcWordWrapPositionA takes a scale, and imgui means size / FontSize by that --
the ratio between the size being rendered and the size the face was baked at
(imgui_draw.cpp, CalcTextSizeA). We were handing it ImGuiHelpers.GlobalScale.

That is the same number today, but by coincidence rather than by design. Dalamud
bakes every font at SizePx * GlobalScale and then divides the metrics back down,
so g.FontSize / font->FontSize lands on GlobalScale for every handle regardless
of its size. The coincidence holds only while one face draws a line.

The typography work starting with this cycle puts a second size into the same
line, and there the two numbers separate: the wrap would be computed for the
wrong size while CalcTextSizeA keeps measuring with the right one. Measured
height and drawn wrap would drift apart, and the virtualised clipper plans
against the measured value.

No behaviour change expected here -- the expression evaluates to what the old
constant already was.
2026-08-19 09:43:19 +02:00
JonKazama-Hellion b388dcb2de chore(release): close the v1.12.0 cycle
Version to 1.12.0 in the csproj, with the changelog and roadmap entries for the
local state. Not published: the public release stays at v1.5.6, repo.json keeps
its 1.5.6.0 manifest and all three download links are untouched.

The changelog leads with the storage change rather than burying it under fixes.
Until this release the unknown-channel failsafe was applied to known channels
too, so an installation that had unticked channels and left the failsafe on was
storing more than the grid said. From here the grid decides, which means those
installations store less than they did yesterday. Nothing already written is
touched, but a user who compares the database against last week should find the
reason in the notes and not have to guess.

Config version 25 is recorded there for the same reason. There is no migration
behind it -- the storage rule changed shape, and the stamp says so.

Known issues carry the honest tail: the database viewer and the emoji picker are
still English, 245 orphaned resource keys remain as the inventory of what the
v1.6.0 rebuild lost, and the licence text still contradicts itself between the
About tab and the translated resources.
2026-08-19 08:35:18 +02:00
JonKazama-Hellion e0c9efca05 i18n: the five spots the smoke test found, and a BOM in the export
Reported from a real pass through the window.

The theme categories were a static readonly array, so the five names
froze at whatever language the plugin started in and a runtime switch
relabelled the entire window except them. Same shape as the layout
labels earlier in this cycle; this one got missed because replacing the
literals with resource lookups looks finished until you actually switch.

The status bar built its counts from English literals -- tab, tabs, msg,
tell, tells -- and the privacy pill said "Privacy-First" in all 25
files. The thousands separator follows the user's culture now too, so
German reads 1,2k rather than 1.2k.

The live preview claims to show what the window will look like. It was
showing English channel names next to a translated placeholder, which is
worse than either. Channel labels come from ChatType.Name() now and the
status slots share the strings with the real status bar. The four mock
chat lines stay English on the earlier decision.

And the export wrote a byte order mark. Encoding.UTF8 emits one, and a
leading U+FEFF makes the JSON invalid for every strict parser --
confirmed against a real export from the game, where python's json.load
refused the file. CSV keeps its BOM, because without one Excel guesses
the codepage and mangles every non-ASCII name.

The self-test that was supposed to catch that read the file with
File.ReadAllText, which strips a BOM while detecting the encoding. It
reads bytes now.

The status bar tests asserted English literals and started failing on a
German machine -- they pin a fixed culture now instead of inheriting the
locale of whoever runs them.
2026-08-19 08:24:31 +02:00
JonKazama-Hellion fdb1a98519 fix(privacy): the cleanup could never be applied, and three more from the audit
The cleanup preview marked itself stale before it could be drawn. The
gate bumps a revision on release so a preview cannot survive a wipe; I
then made the preview take the gate, so its own release invalidated it
every single time and the apply button never appeared. The feature has
been shipping non-functional since it was written, with a self-test that
asserted the exact bump that killed it.

Read-only operations no longer move the revision, and preview and
maintenance have their own marks instead of borrowing Cleanup -- which
also stops the five-second metadata refresh from expiring previews, and
stops the UI announcing "another operation is running: cleanup" during a
VACUUM.

The JSON export produced invalid JSON. The chat relation kinds were
interpolated straight into the output, and interpolating an enum writes
its member name, so every message with a recognised relation came out as
"source_kind":LocalPlayer. That is the file a GDPR access request goes
out on. The self-test wrote a JSON file and never parsed it; it does now.

Retention with the limit at zero still deleted. The slider is labelled
"0 = never" and the sweep seeded 31 spec defaults unconditionally before
reading the user's overrides, so zero still lost free company, linkshell
and party history after ninety days -- and the short-circuit written for
exactly this case could never be reached, because the map was never
empty.

A wipe that worked reported that it had failed. VACUUM needs the
database to itself, the refilter walks a lazy reader on the primary
connection outside the lock, and the two collide -- after the DELETE has
committed. The delete paths no longer let that escape: the rows are
gone, an uncompacted file is a housekeeping problem, and telling
somebody their history is still there when it is not is a different kind
of problem.

Also:

- CSV cells starting with =, +, - or @ get a leading apostrophe. The
  content is text other people typed into a chat channel and the file
  exists to be opened in a spreadsheet.
- An export that matched nothing no longer replaces the previous one. It
  used to write its header, move it into place, and then report that
  nothing matched. Dalamud's save dialog offers no overwrite
  confirmation to fall back on, so this is the part that had to move.
- The retention sweep says so when it loses the race for the gate, and
  routes its notifications through the teardown check like everything
  else.
2026-08-19 07:17:33 +02:00
JonKazama-Hellion 9ea9e96145 fix: close what the style review found, starting with a gate the metadata skipped
The real defect first. RefreshDatabaseMetadata was the one worker of six
that never took the shared lock, and its flag was the one of six missing
from the tab's busy state. It calls MessageCount, which holds the read
lock, so a wipe could start while it was in there -- and the tab would
not have known to grey the button, because it could not see the worker.
Both halves fixed. The pattern is why: seven near-copies of one worker
skeleton, and each copy decided something slightly different.

The clear button failed silently when its thread could not start. The
most destructive control in the plugin, pressed, and nothing happens,
with no way to tell that from a wipe that worked -- while the three
harmless workers beside it do report. Maintenance was the mirror: its
comment promises refusals are said out loud, and then swallowed the
actual failure. Three start-failure paths also bypassed the notify
helper that carries the teardown check, three weeks after it was added
for exactly that.

The database numbers now wait for a real read, like the clear hint
already did. Zero bytes and zero messages read as an empty database, not
as a number nobody has fetched.

SelectionAfterDelete is gone, with its three tests. The accordion has no
selection, so its return value went into a discard -- a function
answering a question the interface does not ask, with green tests
guarding nothing. The project's own self-test README calls that the
anti-pattern of record.

Six new keys replaced by the translated orphans that already said the
same thing. A commit earlier in this cycle is literally called "stop
duplicating a key" and these went past it. The duplicate button also had
the label "Add", which is the one string out of ninety-four that was
never written.

Tests: CleanupDeleteTypes had none, and with the failsafe on -- how a
fresh config ships -- it is the path every cleanup takes. Four now,
including the one that matters: an empty list deletes nothing rather
than everything.

And a self-test for the gate wiring, which is what would have caught the
metadata worker. The unit tests prove the gate works; nothing proved the
workers use it.
2026-08-19 07:09:54 +02:00
JonKazama-Hellion e7b76fb21b chore(i18n): remove the keys whose features were removed on purpose
Fifty-four keys across 25 files, and a script that can find the rest.

The script reports rather than deletes, because a key with no caller is
a question and not a verdict: this cycle has twice found one that only
described a feature whose button was torn out, and deleting it would
have made the restoration cost 25 files of re-translation. The answer
lives in the git history of the deletion, not in a grep.

So only the ones where that history says the feature went on purpose:
the web interface, the settings card overview the sidebar replaced, the
save-and-discard model this window does not have, the LiteDB migration
dialog, and three one-time announcements for versions long past.

Plus nine this cycle superseded itself, including the three notes
telling the reader to press Save first.

251 keys still have no caller. That is not a to-do list -- it is the
inventory the search pass turned up: timestamp layouts, collapse
duplicate messages, the About tab's prose, the honorific glow, the
novice network button. Every one of them describes something that used
to work. They stay until each has been decided one way or the other,
which is the whole premise of this cycle.
2026-08-19 06:51:56 +02:00
JonKazama-Hellion bbfb9fc630 feat(tabs): the tab editor is back
There has been no way to create a tab, delete one, reorder them, or
choose what any of them collects since the settings window was rebuilt
in May. The five tabs a config happened to have were all a user could
ever have. Every label for this was sitting in the resources, translated
into 25 languages, with no caller.

An accordion, not the list-and-detail pane the plan sketched. The
settings column is narrow, every other tab in this window is a stack of
collapsible sections, and a split pane inside one of them would be the
only thing here that reads differently without buying anything.

Channels go through the matrix that already existed, unchanged: it knows
the groups, the sub-matrices and the ExtraChat channels, and it is
localised. What it does not know is copy-on-write -- it mutates the
dictionary it is handed -- so it never gets the tab's own. Edits land in
a working copy and are published as one reference swap when the user
leaves the tab, and only if something actually changed.

Saving is deferred behind a dirty flag with a short idle, not
IsItemDeactivatedAfterEdit. That idiom defers for sliders and text
fields, which stay active across frames; a checkbox activates and
deactivates inside one click, so it would fire exactly as often as the
return value and write the config file once per box.

Deleting closes the pop-out first, or the pool keeps a slot bound to a
tab that no longer exists. The last editable tab cannot be deleted at
all: the message list has no empty state. Temp tabs are not editable
here -- their name is a conversation partner and the auto-tell service
owns their lifetime -- so they are skipped entirely.

Also E2: Tab.AddMessage stamps LastActivity for every message now. The
condition that used to gate it filtered on InactivityHideChannels, a
setting belonging to hide-when-inactive, and that feature lost its
reader in cf4705e. Which tell tab the pool drops first -- the only thing
that reads the stamp -- was hanging on a setting for something that does
not happen. The three channel fields behind it are gone.
2026-08-19 06:50:23 +02:00
JonKazama-Hellion 3a1b863def i18n: adopt the client's word for tell, and translate the appearance tab
Two decisions, both yours.

Where Square Enix ships a client in a language, that client's word wins.
German says Flüstern, French message privé, Japanese テル, Korean
귓속말, Simplified Chinese 密语. Everywhere else there is no official
client and the loanword is what players actually say, so it stays.

That meant rewriting the whole corpus in those languages rather than
just the new keys, which is the reason the split existed in the first
place: forty German values and thirty-seven French ones carried the old
word. /tell is untouched, because that is a command and not a noun.

The mechanical pass left French with three agreement errors -- "des
message privé", "ce onglet", "messages de message privé" -- which is
what happens when you substring-replace a language with gender and
number. Fixed by hand.

Traditional Chinese keeps 悄悄話, which the file already used nineteen
times; it has no official client of its own.

The appearance tab is translated as well. Thirty keys: the colour
editor's groups and buttons, the theme categories, fork and import and
export, the font labels and the preview's input placeholder. Theme token
names stay English -- WindowBg and TextPrimary are JSON keys, not
prose -- and so do the brand strings.

465 keys, 25 files, no gaps, no orphans, no placeholder drift.

Still English and not in this commit: the database viewer behind
/hellionView, which is a documented user command rather than a
developer tool, and the symbol picker. Both are their own block.
2026-08-19 05:11:05 +02:00
JonKazama-Hellion 5991f49c59 i18n: hold the new strings against the glossary the plugin already had
A language review over all 24 files found that the translation batch had
been written as if the file were empty. It is not: eleven years of
FFXIV vocabulary and several hundred existing values already decided how
this plugin says things, and the new strings disagreed with them.

Three said something wrong rather than something unusual:

- Norwegian called opacity "tetthet", which is density -- and the same
  file uses that exact word for compact density, so one word stood for
  two different settings.
- Danish called the brand section "Brand", which in Danish is fire.
- Turkish called a manifest a notification, in a window that already has
  a notifications section.

Then the glossary itself. "tab" is zakładka in Polish, tab in Romanian
and Danish; "plugin" stays plugin in five languages that had translated
it; "pop-out" is a loanword in six. The Shift key keeps its name in
Swedish, Finnish and Italian, because that is what is printed on it.
Fixing pop-out also shortened the three longest row labels in the batch
past the point where SettingRow would have clipped them.

Czech was the clearest outright error: the existing file addresses the
reader informally throughout, and five new strings switched to the
formal form.

And a gap in my own previous fix: I had moved four of the five tell
strings to the established loanword and missed the fifth pair, so the
failed-tell warning still said "Flüstern" while its neighbours said
"Tell".

435 keys, 25 files, no gaps, no orphans, no placeholder drift, and every
one of the five tell keys now carries the same word in every language.

Whether German and French should say Flüstern and message privé rather
than tell is a real question -- both game clients do -- but that is a
glossary decision for the whole file, not something to introduce through
four new keys.
2026-08-19 00:28:24 +02:00
JonKazama-Hellion b3c0ec73ca i18n(settings): keep the game's own vocabulary, and stop duplicating a key
A review pass found the translation commit had introduced a split rather
than closed one.

Every existing string in this plugin leaves "tell" untranslated -- it is
what the game calls the thing, in twenty values across the German file
alone. My new keys translated it, so the channels tab showed "Auto-Tell-
Tabs" and, two rows below, "Flüstern automatisch öffnen". Thirteen of
fourteen sampled languages had the same break. The four affected keys
now use the established word, which also fixes a German line that had
tells "aufgehen" like a door.

Turkish said the opposite of what the control does: saydamlık is
transparency, the slider is opacity, and 1.0 means fully opaque. Every
other language uses the opacity word. Corrected, along with the inactive
one beside it.

Compact density had grown a second key for a field that already had one.
Appearance_UseCompactDensity_Name and _Description were sitting there
with no caller -- which is precisely what this cycle exists to fix -- so
the chat tab uses those and my duplicate is gone again. The German
wizard label for the same field said "Kompakter Density-Modus"; it says
the same thing as the other two now.

Also: Hungarian called a pop-out window "kiemelt" (highlighted), the
project's word is "kiugró"; German called it "ausgeklappt", which is
what a menu does; Italian and Polish had a clumsy inactive-opacity
label.

435 keys, all 25 files, no gaps, no orphans in either direction.

One claim in the previous commit was wrong and is worth stating plainly:
it said only log lines, thread names, developer tools and brand strings
remained English. The appearance tab is still English throughout -- the
theme picker, the colour editor, the font section, the live preview --
and so are parts of the database viewer, which is a documented user
command, not a developer tool. That is a separate block, not a footnote.
2026-08-19 00:24:28 +02:00
JonKazama-Hellion 83306f1f47 i18n(settings): translate the settings window
The settings window was rebuilt in v1.10.0 and v1.11.0 with its labels
written straight into the C#. Every section heading and most row labels
across five tabs read English in all 25 languages, which the memory
notes had accepted as a known backlog.

Forty-nine keys close it: seventeen section headings, the rows under
them, and the two layout choices. All 25 languages, 437 keys each, no
gaps and no placeholder drift in either direction.

The layout labels are a property rather than a static array now. A
static one would hold whichever language the plugin started in, and this
plugin switches language at runtime.

What stays English, deliberately: log lines and thread names, which no
user reads; the two developer tools behind Shift plus Ctrl+Shift, per
the decision that developer surfaces stay English; and the About tab's
brand lines, attributions and licence identifiers, which are names.
2026-08-19 00:08:19 +02:00
JonKazama-Hellion 6bb020547d feat(tabs): groundwork for the tab editor
The two halves that can be settled without a window, before the window
exists.

Concurrency first, because the editor is the first thing that ever
writes SelectedChannels after load. All three channel-filter fields are
read without a lock from the pending-message thread, the filter worker
and the draw thread, and mutating a live Dictionary while Matches walks
it is the standard way to get a wrong answer on somebody else's stack.
ReplaceChannelFilter builds the replacements and swaps the references,
so a reader sees the old set or the new one and never half of either.

It deliberately stops short of making the three writes one atomic step.
A reader can catch the new dictionary with the old ExtraChat flag for a
single message, which the editor's closing clear-and-refilter
reconsiders anyway. Doing better would mean one reference for all three,
and all three are serialized fields whose shape the config file already
has.

Then the index maths, which is where temp tabs make this more than list
arithmetic. They live in the same collection, they are not editable --
their name is a conversation partner and deleting one would be deleting
a conversation -- and a move has to step over them rather than swap with
them, or moving a tab down and back up would not return it to where it
started. Reversible in the editable order, which is the order the user
sees; the sidebar draws temp tabs under their own headers regardless of
where they sit in the list.

Twelve facts, and one of them started out asserting the wrong property:
that the whole list is restored by a move and its reverse. It is not,
and it does not need to be.

The last editable tab cannot be deleted. The message list has no empty
state, so a window with nothing to draw is not a state to offer.
2026-08-18 23:39:43 +02:00
JonKazama-Hellion 8e38e3e805 refactor(config): delete what was never read, restore what was only orphaned
Block D of v1.12.0. The line between the two is the whole job, and I got
it wrong once on the way: six cache fields on Tab looked dead because
nothing writes them, and nothing writes them because AutoTellTabTint and
TabTintCache went out with the chat window in cf4705e. Deleting the
fields would have cemented a loss instead of recording a decision.

So they are back, and the sidebar uses them again: an auto-tell tab is
tinted and glyphed from its partner, twelve colours against seven icons.
Four open tells are no longer four identical envelopes in one colour.

Their own header promised the same partner keeps its colour "across
sessions" while hashing with string.GetHashCode, which .NET salts per
process -- every game start reshuffled every tab. FNV-1a now, with a
lowbias32 finalizer that is not decoration: without it a probe over 144
similar keys reached six of the twelve colours, because the caller takes
the low bits with a modulo and FNV leaves those correlated. Three pinned
values guard it, which is also the only assertion that can catch a
regression to a salted hash.

The same question, asked of the three hide conditions this block had
quietly orphaned: HideDuringCutscenes, HideInBattle, HideWhenNotLoggedIn
all had readers in v1.5.6 and lost them in the same commit. Two of them
are states rather than conditions -- a cutscene the user dismissed stays
dismissed until it ends, and combat must not seize a chat that is
already hidden for another reason -- so they come back as a small state
machine with eight pinned transitions, and three toggles whose labels
were already translated in all 25 languages.

Actually deleted, with a reader search each time:

- Six per-tab hide fields. Their reader was the pop-out window and it
  stopped consulting them in cf4705e. Per-tab was the wrong unit anyway:
  "hide during cutscenes" is a statement about the screen.
- Tab.ChatCodes, whose migration the v16 schema gate had already made
  unreachable.
- InactivityHideTimeout and InactivityHideActiveDuringBattle, MaxLinesToRender
  which had stopped bounding anything, and the 155 lines of
  Configuration.UpdateFrom with no caller at all.

Config version 25, at all three places that carry it. No migration step:
the gate only refuses anything under 16 and Json.NET drops keys it does
not know, so the deleted fields simply stop being written.

One thing a review pass caught that matters more than any of the above:
the clone parity guard had gone hollow. It compares collections by
count, ChatCodes was the only collection the probe seeded, and removing
it left the guard comparing zero against zero. Verified by making
Tab.Clone discard both remaining collections and watching every
assertion stay green. The probe seeds them now, and the same sabotage
fails as it should.
2026-08-18 23:36:54 +02:00
JonKazama-Hellion 6829a80ff2 refactor(wizard): drop LoadPreviousSession, which never did anything
The wizard asked for it, coupled it to a neighbour, listed it in the
summary as applied, and wrote it to the config. No code in the plugin
has ever read it. A wizard that collects a decision and reports an
effect that does not happen is worse than one that never asked.

Its partner, FilterIncludePreviousSessions, has a real reader and stays.
The coupling was two-way -- switching this on forced the partner on,
switching the partner off forced this one off -- so removing it leaves a
single checkbox that means what it says, and the summary line now
reports the setting that actually took effect.

The self-test asserted that skipping step 3 does not overwrite either
field. That assertion is rewritten rather than repaired: it was pinning
the null-semantics of the wizard's pending state, which still matters,
just with one field instead of two.
2026-08-18 22:54:06 +02:00
JonKazama-Hellion e8d06e05fa fix(input): put the right-click menu back on the input field
Reported by a tester: the input field in v1.5.6 had right-click actions,
the current one has no right-click at all.

Correct, and the commit before this one put those actions in the wrong
place. The v1.5.6 menu was ImRaii.ContextPopupItem("ChatInputContext")
bound to the input field itself; I hung the two token entries off the
chat-message menu, where the rest of that window's items had landed.
They are on the input field now, which is also where they are useful:
you insert a token while composing, not while reading.

Two details from the original that the misplaced version had lost:

- The agent pointers are null-checked. Both can be null during a zone
  transition, which is exactly when somebody is most likely to be typing
  a flag into party chat.
- Inserting refocuses the field and puts the caret behind the token.
  Picking from a menu and then having to click back into the field is
  the kind of friction that makes a feature go unused.

Hiding the chat is not repeated in the menu. It was in the v1.5.6 one,
but it has its own button two widgets to the right now, and one way in
is enough.
2026-08-18 22:45:36 +02:00
JonKazama-Hellion 3cb20b6f65 feat(chat): insert map-flag and item-link tokens again, and finish the resx parity
The two menu items went out with the v1.5.6 chat window in cf4705e.
Their strings stayed, in the base file only, so the feature was gone and
its labels were untranslated in all 24 other languages.

They live in the chat context menu now, next to hide-chat, which is
where the rest of that window's items ended up. The game expands <flag>
and <item> at send time, so appending the literal token is the whole
implementation; each entry is disabled while its precondition is missing
so a token cannot be sent only to expand into nothing at the other end.

ChatLog_ScrollToBottom_Tooltip is the one that stings: it has had a
caller since v1.9.0 and existed in the base file alone, so every player
outside English read that tooltip in English.

All three are translated now, and with them the resource files are at
full parity for the first time -- 25 files, every key in every one.
2026-08-18 22:43:09 +02:00
JonKazama-Hellion 75c4acd19a feat(settings): make eleven settings reachable again
Every field here has a reader in the running plugin and had no control
in the window. The config file was the only way to any of them.

HideChat is the one that mattered. It defaults to on, it suppresses the
game's own chat window, and the only other path to it is a right-click
item that sets it to true and can never set it back. Anyone who used
that item once had to edit JSON to get their chat back. The new toggle
reads and writes the same field, so the two agree instead of fighting.

The rest, by tab:

- Window: the three remaining hide conditions, the preview minimum that
  belongs to a toggle already on screen, native item tooltips and their
  offset.
- Chat: an emotes section holding the BetterTTV switch, the cache state,
  and an editor for the blocked-code list that has been in the config
  since v1.0 with nowhere to edit it. Blocking one code is a finer
  instrument than switching emotes off wholesale. Plus auto-translate
  sorting.
- General: the failed-tell warning. The game reports a failed tell in
  the log only, where somebody who is typing does not see it.
- Data & Privacy: battle messages. It decides whether battle lines are
  persisted at all, which makes it a storage decision rather than a chat
  one, and it sits in front of the whitelist rather than inside it.

MaxParallelPopouts stays out. It is read once in the pool's constructor,
the windows are registered once, and registering at runtime is
explicitly forbidden -- a slider would do nothing until a reload, which
is exactly the kind of decoration this cycle exists to remove.

Four new strings in all 25 languages; the other fifteen labels were
already translated and waiting.
2026-08-18 22:40:54 +02:00
JonKazama-Hellion 1bb968211b feat(tabs): give pinning a way in, and a way back out
Pinning has been complete since v1.4.7: pools, a cap of five,
persistence, logout symmetry, the notification when the cap is hit. The
menu that called it went away, and nothing has called it since.

That is not only a missing feature, it is a dead end in saved data. A
tab pinned in v1.5.6 survives every save and load and permanently
occupies one of the five slots, and there has been no way anywhere to
release it. Unpin is the reason this task exists.

So the context menu grows a pin section for temp tabs, and the sidebar
grows the marker that says which rows are pinned -- a small thumbtack in
the icon's lower left, drawn from the row's own rectangle so it claims
no layout of its own. The unread badge owns the upper right, and badges
in this sidebar are where drawing into unreserved space caught this
project last.

At the cap the item is disabled rather than hidden: that is a state the
user can undo by unpinning something, and the tooltip switches to say
which. Five translated strings that had no caller now have one.

Promote-to-permanent stays out. It was removed on purpose after a tester
kept hitting it by accident. Reconnecting every method that lost its
caller, without asking why it lost it, would rebuild the problem this
cycle is supposed to be cleaning up.
2026-08-18 22:35:13 +02:00
JonKazama-Hellion 4f3bdc3c7b fix(privacy): translate the channel list and give it back its presets
Reported after a translation pass: the channel list in Data & Privacy
reads English in every language. It was not, as assumed, the client's
own naming -- the list called ToString() on the enum member, so it
showed "FreeCompanyLoginLogout" while Language.ChatType_* sat next to it
holding "Freie Gesellschaft (An-/Abmeldung)" in all 25 languages.

Fixing the label exposed how little else the list had. Six translated
strings written for exactly this control had no caller: the explanation
of what it does, the note that it governs the database and not the chat
window, and three presets -- data minimisation, select all, deselect
all. Eighty-nine checkboxes without a "recommended" button is not a
choice anyone makes.

So the list now carries the same eight groups the export uses, with the
individual channels one fold away. It is the one control that decides
what reaches the database; the two screens describing channels the same
way is worth more here than anywhere else.

The unknown-channel switch gets its description back, and the telemetry
section stops being the last English literal in the tab. It stays a
statement rather than a switch: a toggle would imply there is something
to turn off.
2026-08-18 22:30:12 +02:00
JonKazama-Hellion 9b634f54e9 fix(tabs): stop a tell from a popped-out partner hijacking the main window
Reported from the field: a new tell from someone whose tab is popped out
throws the main window onto the General tab, every time.

The router revealed the tab by activating it in the main window. That
window does not display a popped-out tab -- PickMainActiveTab re-anchors
on the next frame, and it anchors to the FIRST non-popped tab in list
order, not to the one the user was reading. So the reveal did nothing it
intended and threw away the active tab on the way.

Nothing needed revealing in the first place: the tab was already on
screen in its own window. That decision now lives in PlanTellReveal,
next to the pop-out helpers it belongs with, pure and pinned by nine
facts -- the mode, the switch and the popped-out state have eight
combinations between them and only two of them should touch anything.

ActivateTab refuses a popped-out tab outright as well. The router is the
caller that got it wrong, but the invariant belongs to the window: its
active tab is never one that something else is drawing.
2026-08-18 22:25:23 +02:00
JonKazama-Hellion 4f4f5fc86a docs: finish holding the documentation against the code
The first pass through A6 caught the dead file paths and the two GDPR
sections. A review pass walked every remaining claim and found eight
more that no longer describe the plugin.

The privacy notice carries a "last reviewed" stamp and commits, in its
own text, to keeping it accurate for the version it describes. It still
said v1.1.0 after the block that rewrote two of its sections.

Both documents announced two outbound network calls in their opening
paragraphs. The Lodestone font download went away in v1.0.4 and the
notice explains that further down, so the summary contradicted its own
body. There is one call, and it is BetterTTV.

The emote cache is `EmoteCacheV1/`, which the notice states correctly in
one place and wrongly in two others, two lines above a line this cycle
had already touched.

The list of buttons that open a browser named a Ko-fi page that appears
nowhere in the source, an issue tracker and a website that have no
button, and left out the Discord invite and the two Honorific links that
do. In a section that exists precisely to enumerate where a click sends
you, both halves matter.

The README described the pop-out input bar as an opt-in under a settings
section that does not exist. Neither does the switch: PopOutInputEnabled
has no reader, the input bar is unconditional, and the field belongs on
the deletion list. Said plainly instead.

Also: the export narrows by age, not by a date range, in both documents;
the tab is called About, not Info, and it has no per-translator list;
the sections are Colours and Integrations.

Plus a note the users affected by it deserve: the v24 migration switches
the privacy filter off where it was on with nothing selected, and until
now that was only in the log.
2026-08-18 22:14:45 +02:00
JonKazama-Hellion 06ef0bfb1c fix(input): let the arrow keys walk the sent-message history again
Reported against v1.11.0: type a command, send it, need it again, and
up-arrow does nothing. v1.5.6 recalled it.

Everything needed was already in the tree. InputHistoryService holds the
last thirty entries with move-to-newest dedup, CompactInputHistoryNavigator
owns the cursor maths, and both have their own test mirrors. Neither had
a single caller, and the input field never set CallbackHistory, so ImGui
had no reason to raise the event in the first place.

So: the flag goes on, the callback grows a history branch, and TrySend
pushes the trimmed line before it clears the buffer. Editing ends the
walk, otherwise down-arrow after changing a recalled line would jump to
the next entry and discard the edit.

The cursor is per input bar while the history is global. Which line each
window is looking at is not something the others should inherit.
2026-08-18 22:13:41 +02:00
JonKazama-Hellion 0279a1a9d6 fix(privacy): close the gaps three review passes found in block A
The worst of them made the block's own privacy promise backwards.

PrivacyPersistChannels was given a non-empty field initializer so a
fresh config would record conversations only. Dalamud deserialises with
Json.NET's defaults, which means ObjectCreationHandling.Auto: a
collection field that already holds items gets *populated*, not
replaced. Verified against Newtonsoft 13.0.3 -- saved [] loads as the
initializer, saved [Say] loads as initializer plus Say. So the change
would have unioned the privacy-first list into every existing config on
load and switched channels back on that the user had unticked, while
also making the v24 migration unreachable and its self-test vacuous. The
field is empty again and the seeding moved to CreateFresh, which only
runs when there is no config file at all.

Cleanup could delete a channel it had promised to keep. The allowlist
could only name channels that were already in the database when the
preview ran, so an unrecognised channel whose first message arrived
afterwards fell outside it. Where the failsafe is on, the deletion now
names what goes -- known channels that are not on the list -- instead of
what stays. The window closes completely, and a listed channel that
happens to be empty right now is safe for the same reason.

The cleanup preview was the one long operation that never took the
shared lock, while holding an open reader across a full-table scan.
That is precisely the case the lock was written for.

Clearing the history reported success when it failed. ClearMessages
purges the full-text index between the delete and the VACUUM; if that
step throws, the plaintext stays on disk and the user was told it was
gone. It has its own error string now, in all 25 languages.

Also:

- One busy state for the whole tab. Cleanup, clear, maintenance and
  export reach the same store, and per-section flags left two
  destructive buttons live at once. The lock turned that into a refusal
  rather than damage, but a refusal you have to trigger to discover is
  not an answer.
- The gate carries a revision, bumped by every mutating operation that
  finishes. A preview taken before a retention sweep no longer passes as
  current afterwards: comparing it against the settings alone cannot see
  that the rows it counted are gone.
- Database metadata moved to a worker. Checking "is anything busy" first
  is not enough, because an operation can take the lock in the gap
  before COUNT(*) runs, and then the game stands still for a whole file
  rewrite.
- The clear hint stays hidden until the count has actually been read.
  "0 messages are stored" in front of the clear button is a lie told at
  the worst possible moment.
- Refusal notices read the operation once. Guard and name were two reads
  of the same field, so a run finishing in between printed a sentence
  that stopped at the colon.
- The retention sweep cannot start twice. The gate only goes busy once
  the worker reaches TryBegin, and the due-check runs every tick.
- Teardown waits up to five seconds for the store to come free rather
  than disposing the connection under a running VACUUM.
- Maintenance has its own flag and says so when it is refused; reload
  gets the same guard as its neighbour; the breakdown tree keeps its
  open state across a language switch.
2026-08-18 22:13:33 +02:00
JonKazama-Hellion 1987d745d8 docs: hold the documentation against the code
Every claim in the user-facing docs, checked against what the plugin
actually does after A2 to A5.

The two GDPR sections in PRIVACY.md describe features that only exist
again as of this cycle, so they now name the screens they live on and
say what the cleanup does with a channel this build does not recognise.
The export sentence promised a date range; the form offers an age in
days.

PRIVACY.md also named "Show emotes" in Settings as the way to stop the
one outbound call the plugin makes. That switch has had no control since
May, and a documented opt-out that only exists in the JSON is not an
opt-out, so the toggle is back in the chat tab. Both its strings were
already translated.

Dead paths: the README source tree still listed a file deleted in May,
docs/IPC.md cited a window that no longer exists, the first-run wizard
pointed at the same removed file, and the theme authoring guide sent
readers to a Themes tab that is called Appearance.

The changelog lost two double blank lines that were failing markdownlint
and holding preflight red. Preflight is green again.

Historical documents keep their old paths on purpose: the changelog and
the AI disclosure describe what was true when they were written.
2026-08-18 21:51:15 +02:00
JonKazama-Hellion e24ea79302 feat(privacy): reconnect database maintenance and the manual retention run
Two sections that had backends and no buttons.

Database: path, size, WAL size, message count, and a clear button. The
numbers refresh at most every five seconds and not at all while a long
operation owns the store -- MessageCount takes the read lock, and asking
for it during a VACUUM means waiting for the whole file to be rewritten,
on the draw thread. The old version called ClearMessages straight from
the draw thread, VACUUM included; it runs on a worker now.

One line beyond the old layout sits above the clear button: how many
messages are stored, and that exporting keeps a copy. Whoever is about
to throw the history away should be told there is a way not to.

The legacy Chat 2 files only get a block when they are actually on disk,
and the advanced tools only appear when the section is expanded with
Shift held. The message injector is not back: it was deleted with the
tab and writing 10,000 fake messages into a user's real database is not
something to rebuild on the way past.

Retention: an "apply now" button, the running hint, and the last-run
line, which v1.11.0 shipped as an English literal while both strings sat
translated in all 25 languages. Plus reset-to-spec next to the existing
clear-overrides, since the two answer different questions and both were
already translated.

Retention_Apply_Tooltip stays unused and gets a replacement. It ends
with "Save your changes first", and the window it was written for had a
Save button.

Also here, found while wiring the manual trigger:

DbOperationGate.End now takes the operation it releases. It used to
reset blindly, on the reasoning that a worker must be able to release
from a finally without knowing whether it acquired. That is backwards: a
worker whose TryBegin was refused also runs its finally, and a blind
reset there hands away the lock of whichever operation actually holds
it. Worse than no gate, because the refused worker walks off believing
it did nothing while a VACUUM starts under somebody's open reader.
2026-08-18 21:47:50 +02:00
JonKazama-Hellion 1ab7ba8377 feat(privacy): reconnect the retroactive cleanup
The privacy filter only decides what gets written from now on. Whatever
was stored before the user narrowed their channels stays there until
something removes it, and that something has had no button since May.

Two rules shape the section, both because this deletes history and
cannot be undone:

- Without a preview the apply button does not exist. Not greyed out,
  absent. A disabled button is something a user waits for; a missing one
  is something they have to go and earn.
- A preview that no longer matches the settings counts as no preview.
  The old version only recoloured the number and left the button live,
  so a changed whitelist could be applied against counts computed for
  the previous one.

The mapping from the live rule to CleanupRetainOnly is the part worth
reading twice. CleanupRetainOnly takes one set and deletes everything
else, so it can only stand in for the live rule where that rule narrows
something: filter off means nothing is filtered, and an empty list means
a full wipe, which has its own button and its own confirmation. Both
cases now say so instead of offering a destructive action that does not
mean what it looks like.

Inside that, the allowlist is the whitelist itself plus any stored
channel this build does not recognise while the unknown-channel failsafe
is on. Deriving it from the counts instead would delete messages that
arrive on a whitelisted but currently empty channel between the preview
and the apply, and dropping the unrecognised ones would defeat the
failsafe, which exists to hold on to a new patch's channel until the
user has decided about it.

The preview runs on a worker over its own connection. It is a GROUP BY
across every stored row, the old version ran it inline on the draw
thread, and holding the read lock for it would stall UpsertMessage on
the framework thread for the length of the scan.

Cleanup_Help_SavedNote stays unused: it tells the reader to press Save
first, and the window it was written for had a Save button.
2026-08-18 21:38:34 +02:00
JonKazama-Hellion 94af81a961 fix(privacy): let the channel grid actually decide what is stored
IsAllowedForStorage applied the unknown-channel failsafe to known
channels too. Untick Say in the grid, leave "Save unknown channel types"
on, and Say kept being written -- and that failsafe is on by default.

So a config that never met the wizard ran with the filter enabled, an
empty list and the failsafe on, which stored everything while the
filter's own description promised "only messages from allowed channels
are written to the database". The grid was inert for exactly the users
who had not been walked through the wizard.

The rule now reads: on the list, or unknown and the failsafe allows it.
A known channel the user did not pick stays out.

That correction alone would turn "stores everything" into "stores
nothing" for those same configs, so two things move with it:

- Config v24 switches the filter off where it was on with nothing
  picked. Same behaviour as before, stated where the user can see it,
  and one line in the log saying so. A config that does have picks keeps
  them and starts honouring them, which is the point of the change.
- A fresh config seeds the list from PrivacyFirstWhitelist instead of
  starting empty. Privacy by Default was already the documented intent;
  it just relied on the hole to stay usable.

The rule lives in its own type now. Configuration implements a Dalamud
interface, and the build suite cannot load Dalamud.dll -- the runtime
resolves the declaring type before reaching the method body, so even a
static call on it fails. Fifteen cases pin the truth table and the
migration condition; the self-test checks the running config is not in
the state the migration exists to undo.
2026-08-18 21:32:02 +02:00
JonKazama-Hellion d59ee62223 feat(privacy): reconnect the message export
The exporter has worked since v1.4.8. The form that drives it went out
with the old settings window in May, which left PRIVACY.md promising an
access request the plugin had no way to answer.

New section in the data and privacy tab: time range, sender substring,
channel groups, format, and a save dialog. Form state lives in the tab,
not the config -- a filter describes one action, and a stale "last 7
days, sender Mira" reappearing weeks later is a worse start than an
empty form.

StreamForExport now takes a caller-owned connection. The reader stays
open for as long as the file is written, seconds to minutes on a large
history, and chat keeps arriving throughout -- so the primary connection
would be read here and written by UpsertMessage at once, and
SqliteConnection is not thread-safe. Holding the read lock instead would
trade that for freezing the game.

ChannelGroups lifts the eight groups out of the deleted tab and finishes
them: 37 of 89 channels belonged to no group and were therefore
unreachable in the UI. Game Master channels follow ChatTypeExt.Parent(),
so GmTell sits with the other tells rather than under system traffic --
an access request that quietly drops part of what it promises is the
dangerous kind of gap.

Also here:

- OpenSecondaryConnection disposes on a failing pragma. Open can succeed
  and journal_mode=WAL still time out, and with Pooling=false the
  connection then survives until a finalizer reaches it. Affects the
  full-text rebuild worker too.
- StreamForExport builds its logger before the reader, so a throwing
  CreateLogger cannot leave a reader nobody owns.
- The export thread takes the gate itself instead of the caller taking
  it first. Acquiring before Start would strand the gate for the session
  if thread creation failed, and the gate also holds back the sweep.
- Notifications are skipped once teardown has started. The thread has no
  cancellation path and finishing the file is right, but reporting it to
  a plugin that is gone is not.
- Transient widget rows that return their value instead of saving it.
  Writing the config file on every keystroke of a sender filter would be
  both pointless and slow.
- Five translated keys for "another database operation is running", in
  all 25 languages. Two of the four operation names have no trigger yet;
  they arrive with the cleanup and maintenance sections.
2026-08-18 21:25:10 +02:00
JonKazama-Hellion 90bf986f76 refactor(export): read text from chunks, write the file atomically
Two changes to MessageExporter before it gets a caller.

It read SenderSource and ContentSource, the raw SeStrings. TextValue on one
holding an auto-translate phrase reaches SeStringEvaluator, which asserts it is
on the main thread and throws unconditionally when a macro resolves a global
number. An export belongs on a worker, so that would abort it partway and leave
half a file.

The plan called for resolving text in batches on the framework thread. Not
needed: Message.Sender and Message.Content are already-resolved chunk lists --
ChunkUtil turns auto-translate into text at ingest, and the full-text index reads
them exactly this way. Same strings, no evaluator, no thread affinity, and no
batching machinery.

Second, the file handling. The format was validated after the StreamWriter was
opened, so an unknown format left a zero-byte file where a previous export had
been. It is checked first now, and the write goes to a .part file that is moved
into place at the end. A crash halfway used to leave a file that opens cleanly
and is quietly incomplete -- which on the path a GDPR access request goes out on
is worse than an obvious failure.

Almost none of this is reachable from the build suite: ExportToFile takes
IEnumerable<Message>, Message needs SeString, and xUnit cannot load Dalamud.dll
-- even an empty list fails, because the runtime resolves the parameter type
before the body runs. So the format mapping is pinned there and the rest by a new
self-test, which builds probe messages with deliberately empty SeStrings: if the
exporter ever reads them again, the text comes out blank and it fails.
2026-08-18 20:47:45 +02:00
JonKazama-Hellion 22de2de234 docs(db): correct why VACUUM fails against an open reader
The comment said PerformMaintenance inherits a five-second timeout before
throwing. It does inherit that timeout, but it is not what happens here: a VACUUM
on a connection with a live reader fails instantly with 'cannot VACUUM - SQL
statements in progress'.

That is SQLITE_ERROR, not SQLITE_BUSY. Busy handling only covers contention
between different connections, so no timeout applies and no retry helps. The
practical difference matters for the error message the UI will show: the DELETE
has already committed when it fires, so the rows are gone and only the compaction
is missing -- 'deleted but not compacted', not 'failed'.

And PerformMaintenance batches VACUUM, REINDEX and ANALYZE in one statement, so
a failing VACUUM takes the other two with it.
2026-08-18 20:37:40 +02:00
JonKazama-Hellion 6a3bbe2357 fix(ci): let the version check tell a release from a local build
The check demanded csproj, repo.json and every DownloadLink carry the same
version. That is right for a published release and impossible for anything else,
so it went red the moment v1.11.0 closed -- and pre-push blocks on it.

The two states were conflated. repo.json is the distribution manifest, so its
version has to describe what the links actually serve. Claiming 1.11.0 while
every link serves v1.5.6 makes Dalamud offer an update, install the old build,
and offer the same update again on the next launch. Satisfying the old rule
meant building exactly that.

Now: the manifest must always agree with itself and with its links, and the
build must never be older than what is published. --release additionally demands
the three match, which is the mode for cutting a tag and still catches the v1.2.2
burn it was written for.

The link check moved from the csproj version to the manifest version, which is
the pairing that protects users. In the old form a manifest could name a version
none of its links served and pass, as long as the csproj agreed -- the exact
mismatch it now rejects.
2026-08-18 20:28:28 +02:00
JonKazama-Hellion d0eb2934ed feat(db): one gate for every long-running database operation
Generalises the retention-sweep lock, which already solved this for a single
case: it stopped a manual sweep from racing the automatic one, and nothing else.

Export, cleanup and clear need the same protection against each other, and for a
sharper reason. An export leaves a reader open on the primary connection
deliberately outside _readLock, because the enumerator is consumed lazily by its
caller. A VACUUM starting while that reader lives meets an active reader on a
connection Microsoft documents as not thread-safe, and PerformMaintenance sets no
command timeout, so it inherits five seconds before throwing -- after the DELETE
has already committed.

TryBegin refuses rather than queues. Every one of these is user-initiated, and a
wipe that fires minutes after the click is worse than one that declines. End is
idempotent and does not check which operation ends, so a worker that throws
before acquiring can still release from its finally block.

Current is volatile because the draw thread reads it every frame to decide which
buttons are disabled. Blocking on the lock to find that out would freeze the game
for the length of a VACUUM, which is the exact failure this is meant to prevent.

Pure state machine, so the transitions are pinned without a database or an ImGui
frame -- including that exactly one of 64 competing callers wins.
2026-08-18 20:19:27 +02:00
JonKazama-Hellion 125a57167e fix(privacy): purge the full-text index when messages are deleted
messages_fts stores sender and content as plain text, and no delete path touched
it. ClearMessages, CleanupRetainOnly and the retention sweep all removed rows
from `messages` alone, so the readable text of every "deleted" message stayed on
disk.

It was self-sealing. InitFtsReadyCache treats a non-empty index as ready, so
after a wipe the index stayed full, the flag stayed true, and the rebuild that
would have cleared it never ran again.

This is not hypothetical: the retention sweep runs unattended every 24 hours,
so any user with retention on has been accumulating orphaned plain text since
the index shipped. And the plugin says otherwise in two places -- the clear
button promises "Removes all message history. Cannot be restored", and
PRIVACY.md documents targeted deletion as a feature.

Wiping the index rather than deleting matched rows, because message_guid is a
GUID string while messages.Id is a BLOB and the two cannot be joined in SQL. The
index is derived data; it rebuilds from the surviving rows on the next start,
which is both cheaper and provably complete.

CleanupRetainOnly also skips VACUUM when nothing matched, the way
DeleteByRetentionPolicy already did. Rewriting the whole file for zero deleted
rows costs seconds on a large database and gains nothing.

Six tests drive the real store against a real database, since the defect was in
what the SQL did not touch rather than in any computed value.
2026-08-18 20:03:03 +02:00
JonKazama-Hellion 8bf351ba02 docs: correct the untranslated string count
Measured across the whole UI rather than estimated from the settings window:
around 270 visible literals without a resource key, not the hundred the changelog
claimed. The settings window is the bulk of it, but the first-run wizard, the
input bar and the about tab carry their share.

Smoke test for the cycle came back green -- everything works and does what it
says. The untranslated strings are the only known issue.
2026-08-18 19:37:07 +02:00
JonKazama-Hellion f205dd4e54 chore(release): close the v1.11.0 cycle
Version to 1.11.0 in the csproj, changelog and roadmap entries for the local
state. Not published: the public release stays at v1.5.6 and the download links
are untouched.

repo.json goes back to 1.5.6.0. It had been carrying the development version
while all three download links pointed at the v1.5.6 archive, which is a trap
waiting for a merge: Dalamud would offer an update to a version the download
does not contain, install v1.5.6 again, and offer the same update on the next
launch. main is unaffected -- it only ever saw 1.5.6.0 -- but the feature
branches have been inheriting the mismatch since v1.6.0.

The manifest version belongs to what the links actually serve. A local state is
tracked by the csproj and the changelog, which is what they are for.

Testing channel deliberately not opened yet. Publishing 1.11.0 as a test build
would ship a modern settings window alongside a first-run wizard and a message
list that are still stock ImGui -- and 1.10.0 would ship the pinned-tell-history
bug that 1.11.0 fixes.
2026-08-18 19:34:27 +02:00
JonKazama-Hellion d1e12ce866 fix(popouts): restore a way to close a pop-out
Last commit hid the header row when the title bar was on, to stop the tab name
appearing twice. The close button was in that row, and the title bar carries
none of its own -- ShowCloseButton is off because closing has to go through the
pool to release the slot. So a pop-out with its title bar on could not be closed
at all.

Pop-in moves into the input row, alongside the settings and hide buttons that
are already there. It is red, contrast-checked against the button plate it sits
on, and carries a tooltip, since a bare X next to an emoji picker does not say
where the tab is going.

Wired by setter after construction rather than through the constructor: the
window is what the button has to call, and it does not exist yet while its own
input row is being built. Routing it through the graph would close a
factory-callsite cycle MS.DI cannot detect.

The header row is now just the tab name, drawn only when there is no title bar
to carry it.

InputBar_PopIn_Tooltip ships in all 25 languages, including the Designer entry.
New strings get translated with the change from here on, not batched.
2026-08-18 19:21:24 +02:00
JonKazama-Hellion 051fd64857 fix(settings): use the translations that were already sitting there
The window came out half German and half English on a German client. Thirteen of
those labels had a translated resource all along, reachable from no line of
code -- the same defect this cycle has now hit four times.

Most visible: all seven tab names in the sidebar. Settings_Tab_General and its
siblings exist in 25 languages and the sidebar drew "General", "Appearance",
"Chat" as literals. That is the first thing anyone sees in this window.

Plus reduce motion, custom sound volume, show hide button, window opacity, the
window style heading, and the themes folder button.

Deliberately left alone where the wording matched but the context did not.
"Never" exists as a world-suffix option, not as "the sweep has never run", and
"Opacity" exists for a tab rather than a window; reusing either would read
wrong in any language that inflects them differently. Those want their own keys,
not a borrowed one.

What stays English is what has no key at all: the section headings, the keybind
labels, and the descriptions written during this cycle. Roughly a hundred
strings, and adding them means 25 files each -- that is the localisation pass,
not this commit.
2026-08-18 19:15:00 +02:00
JonKazama-Hellion 9c7be4106d feat(popouts): bring the pop-out windows up to the rest
Three things, all visible in one screenshot.

The tab name was drawn twice. The pop-out has a title bar carrying the tab name
and a header row underneath repeating it -- the same string, one line apart. The
header now only draws when the title bar is off, which is the case it was
written for.

The close button was ImGui.Button, so it took the theme's button colours. On
several themes that is a bright magenta plate sitting next to plain text, making
the way out of the window the loudest thing in it. It uses the plugin's own icon
button now: glyph contrast-checked against the surface, danger colour on hover
only.

And the message area gets the same floor as the main log, with the same
restraint -- no accent wash, motes at a tenth. Pop-outs were the last surface
still sitting on flat background while every other window had depth.
2026-08-18 19:09:40 +02:00
JonKazama-Hellion d30922af8c feat(settings): convert the appearance tab, finishing the window
The last six stock collapsing headers are gone, so all seven tabs now read the
same way. Appearance is the one people open most, being where the themes live,
and it was still the odd one out.

Its four components each needed only the heading, so they get a SectionRenderer
rather than the whole widget set -- SettingsWidgets would have handed a colour
editor a Plugin reference it has no use for.

Three of the six could not take a literal key. The colour editor draws its
section seven times with seven titles, so the key becomes a parameter. The theme
picker keys its categories by position, since CategoryMap is a fixed list and
the index survives those names being translated later. And the custom-theme
section takes a fixed key although its label carries a count, or it would reset
every time a theme is imported or removed.

The theme picker's headers also pick up the disabled state properly now. They
sit inside an ImRaii.Disabled while a theme is being edited, and a draw-list
header cannot see that push -- so they had stayed at full contrast while
everything under them dimmed.
2026-08-18 19:07:04 +02:00
JonKazama-Hellion 04f8f1ace8 feat(settings): opaque settings window, contrast applied throughout
The settings window no longer inherits the chat window's transparency.
GlobalStyleScope pushes one opacity for every window in the plugin, so a value
chosen to keep the chat log out of the way was also deciding how readable a
settings dialog is.

The stronger reason is that contrast cannot be computed against a background
that is not there. Behind a translucent window the real background is the game:
a black cave one minute, a snowfield the next. Every foreground measured last
commit was measured against a colour it does not actually land on. Opaque makes
that measurement true.

BgAlpha only reaches the window fill, never the draw list, so the backdrop
cannot observe it -- it takes an explicit override instead of guessing from the
pushed WindowBg.

Contrast now runs through SettingsPalette, so every row and heading gets it
without each call site asking: 4.5:1 for labels and titles, 3:1 for descriptions
and accents. The lower floor on descriptions is deliberate. It preserves the
rank between the two lines of a row, which is why the description is dimmer at
all, while still guaranteeing it stays legible.

The toggle's border is in there too. It is the only thing marking an off switch,
and a border tone that blends into the surface leaves the control invisible.
2026-08-18 19:01:54 +02:00
JonKazama-Hellion 33bcc38581 feat(style): pick foreground colours by measured contrast
The gradient was turned down because text on the lit edge became hard to read,
which fixed the symptom and lost the effect. The real problem is that a theme
picks one text colour while the same text lands on a base surface, a lit edge
and an accent fill, and a value that reads on one can vanish on another. White
iconography on a pale violet accent was the reported case.

So contrast is computed rather than assumed. ColourUtil gains WCAG relative
luminance, the contrast ratio, and EnsureContrast, which walks a foreground away
from its background until it clears a threshold -- 4.5:1 for text, 3:1 for
icons -- and stops at the first step that does, so a colour keeps as much of its
hue as the ratio allows.

Luminance is gamma-corrected now. sRGB is gamma-encoded, so averaging raw bytes
overstates dark colours badly, and nearly every surface here is dark. Mid grey
is 0.216 relative luminance, not 0.5.

The tests caught a real error in the first version: direction was chosen by
whether the background measured below 0.5 luminance. Pale violet sits at 0.39,
counts as dark by that rule, and the function tried to make white whiter. It now
picks whichever end reaches further from the background.

With foregrounds that follow, the gradient goes back up past where it was.

Applied to the sidebar icons and labels and to the segmented control's labels.
The remaining call sites are a polish pass of their own -- this is the machinery
plus the two places that were reported.
2026-08-18 18:51:08 +02:00
JonKazama-Hellion ae9b503776 fix(tells): load pinned tell history after login, not before it
A pinned tell tab came up empty for the rest of the session, reported by a
tester and reproduced from his config.

RehydratePinnedTabs runs from a hosted service at plugin start. It queries tell
history by character, and CurrentContentId is 0 until a character is logged in
-- LastContentId only gets set from the framework tick. The game loads plugins
at boot, so the normal path queries for character zero, finds nothing, and there
was no second attempt: the service subscribed to Logout but not Login.

It defers now when no character is available and completes on the login that
follows. The pending flag keeps a later character switch from appending a second
copy of the history to tabs that already have it.

Two things hid this. Reloading the plugin in a running session, which is what
development looks like, always has a character available. And it only shows up
if you pin a tell tab at all -- the same path for non-temp tabs already handles
the boot case explicitly, one file over:

    if (pluginInterface.Reason is not PluginLoadReason.Boot)
        manager.FilterAllTabsAsync();

Also surfaces FilterIncludePreviousSessions in the Chat tab, which decides
whether the log shows anything from before the current session and had no
control at all -- written only by the first-run wizard, and only if the user
reached step 3. Skip the wizard and it stays false forever. It applies
immediately rather than at next launch, since the user is looking at the window
when they ask for it.
2026-08-18 18:44:54 +02:00
JonKazama-Hellion 57780351d4 feat(settings): convert the remaining four standard tabs
Chat, Channels, General and Data & Privacy now draw the same way Window does. A
half-converted window is worse than an unconverted one: before, all seven tabs
were consistently dated; after the pilot, one looked current and six looked
abandoned, and switching between them made the seam obvious.

Descriptions move out of the help markers and onto the rows. Those strings were
written to be read, and a (?) the user has to hover is where an explanation goes
to be ignored. Several were translated into 25 languages and had never appeared
on screen at all.

Two settings that could not use the standard helpers -- the language picker,
which rebuilds the font atlas, and the keybind mode, whose description depends
on the selected value -- go through a plain Row that hands the caller the control
column and leaves the save logic alone.

Privacy filter labels now come from the resources that already existed for them,
same defect as the channels tab last round: strings present, translated, and
reachable from no line of code.

Four more constructors take a TokenResolver, so this wants the DI smoke pass.
Only the appearance tab still draws stock collapsing headers; its four
components are their own block.
2026-08-18 18:23:34 +02:00
JonKazama-Hellion 7df18bd552 fix(style): shorten the ramp instead of layering it
The dithering attempt made it worse and the reasoning was backwards. Four layers
at a quarter alpha each carry a quarter of the steps each, so every layer bands
more coarsely than the single ramp did, and blending four coarse ramps adds
interference on top. Reverted.

The real variable is distance, not layer count. A ramp has as many steps as it
has distinct alpha values, so stretching it over the full height of a pane gives
each step a stripe twenty-odd pixels tall, which the eye sharpens into
scanlines. Running the same ramp over 190 pixels puts those steps a few pixels
apart, where they read as a falloff.

So: light fading down from the top edge, shadow gathering at the bottom, and a
flat surface in between. Constant alpha cannot band at all, which leaves most of
the pane immune by construction.
2026-08-18 18:14:02 +02:00
JonKazama-Hellion 05b203c85c fix(style): dither the surface tint so it stops banding
"Horizontal scanlines" names it exactly. An alpha ramp from 0x34 to 0 has 52
distinct values, so across a 600px pane each one owns a stripe about 12 pixels
tall, and the eye reads those stripes as scanlines. Raising the contrast only
buys more of them, thinner.

So it dithers. Four ramps at a quarter alpha each, every one ending slightly
lower than the last, so they share a starting colour but run at different
slopes. Their step boundaries land on different rows, and where one layer has
stepped up its neighbours have not, which puts the blend between two quantised
values. Same total tint, four times the effective resolution, three extra draw
calls.

Layers are staggered by slope rather than offset on purpose: shifting them would
leave a gap at the top where fewer layers overlap, which reads as a bright band.
That trades one artefact for a worse one.

The tint is roughly twice as strong now, which the settings pane wanted anyway,
and strength is a parameter so the chat log can stay at 45% of it.
2026-08-18 18:09:46 +02:00
JonKazama-Hellion c1f1c0563c fix(style): tint the surface instead of repainting it
Both remaining complaints had one cause. The window paints its own background,
and the backdrop was filling the same area a second time. Two stacked layers
turn a translucent window solid, which is the density over the chat log.

And an opaque fill has to carry the entire gradient by itself. That is where the
banding came from: a shallow ramp across an opaque surface crosses so few 8-bit
values that each one covers a visible stripe. Nothing sits underneath to break
them up.

So it tints now. Near-transparent white at the top, near-transparent black at
the bottom, straight over whatever the window already drew. The window colour
stays visible, the ramp only shades it, and the game showing through disperses
what little stepping is left. The sidebar does the same with a flat black wash
rather than a repainted darker surface.

Motes are roughly half as bright everywhere, and the chat log takes 10% of that.

DrawVerticalGradient stays for the segmented control, which paints a surface
that genuinely is its own rather than one already drawn underneath.
2026-08-18 18:05:11 +02:00
JonKazama-Hellion 8b96ffb2ec fix(style): let the backdrop follow the window's own opacity
Three problems from one screenshot, and the same root cause behind two of them.

The pane painted at full opacity regardless of the window it sat in. BgAlpha
only ever reaches WindowBg, so a draw-list fill ignores it entirely, and a
deliberately translucent settings window came out as a solid block beside a
translucent chat window. The backdrop now reads the alpha out of the resolved
WindowBg colour and carries it through the gradient, the accent wash and the
motes.

The banding is 8-bit quantisation, not a rendering fault: a gentle ramp across a
tall surface crosses so few distinct values that each one covers a visible band.
Halving the range leaves fewer and fainter steps, and the translucency now
underneath them breaks up what remains.

Motes over the chat log drop to 18%. A settings page is read in glances and can
carry motion behind it; a chat log is read line by line, where anything drifting
behind the text competes with it. Intensity is a parameter rather than a second
particle system, so the two surfaces share one implementation.
2026-08-18 18:01:07 +02:00
JonKazama-Hellion 8ebed6846d feat(style): put the chat log on the same floor as the settings
The motes were too subtle to register, so: seventy instead of twenty-four, wider
radius range, and each one is a soft halo with a brighter core rather than a
flat disc. At this size a single filled circle reads as a speck of dirt on the
screen; the ring around it is what makes it look lit.

The backdrop moves into its own component and the chat log gets it too. Two
windows in one plugin looking like two separate products was half the reason the
settings window read as untouched -- the chat had been reworked in v1.10.0 and
the settings had not, and no amount of work inside one window closes that gap.

No accent wash over the message list. It works on a settings pane, where the top
of the surface is a heading; over a chat log the oldest visible messages would
sit in a tinted band and read as highlighted.

Registered transient rather than singleton, so two surfaces on screen own
separate mote sets instead of sharing one drift pattern -- which would be
visible the moment a popout sits next to the main window.

MainWindow's constructor changed, so this needs the DI smoke pass.
2026-08-18 17:55:44 +02:00
JonKazama-Hellion 76416afe3a feat(style): depth for the settings window
Brief was a mix of Lightless and Character Select+, modern without being
overloaded, and the gradient allowed to show more.

The content pane gets a stronger gradient plus an accent wash falling from the
top edge to about a third of the height. Without it the pane was a neutral box
that happened to sit inside a themed window; now the theme reaches the surface
being read.

Ambient motes drift up behind it. Procedural rather than the image sequence
Character Select+ uses, so there are no assets to ship and they take the theme's
accent instead of whatever was baked into a PNG. Fixed count, fixed arrays,
seeded once, so the layout is identical every session and nothing allocates per
frame. They advance once per frame regardless of how many surfaces call in, and
ReduceMotion skips them entirely -- same contract HoverState already honours.

The tab sidebar was the last stock-ImGui element and had started to look it. Its
entries are drawn now: darker plane than the content pane so the two read as
separate surfaces, a chamfered plate with a solid leading bar for the active
one, hover fading between muted and full text.

Its icons go through the draw list with a font pointer taken outside the scope,
rather than being drawn inside a FontAwesome push. That atlas has no ASCII
glyphs, so any label caught inside such a scope renders blank -- which has
already happened twice in this plugin, once in the tooltips and once in a badge.
2026-08-18 17:50:32 +02:00
JonKazama-Hellion ced7ea0c55 feat(style): headings by typography, surfaces by gradient
Two rounds of screenshots said the same thing twice: the section headings read
against blue themes and vanished against violet ones. The cause was that their
only distinction from a normal row was a fill colour, and no fill works in every
palette.

Headings are typography now. Small caps with wide tracking, no plate, no bar,
followed by a rule that fades out along its length instead of stopping dead. The
weight comes from letterforms and whitespace, which look the same in every
theme. 18px of air above each one does the grouping that the bar used to fake.

ImGui has no letter-spacing, so DrawTrackedText renders one glyph at a time
through a stack buffer. That technique is documented in Character Select+, whose
Boutique style layer solves exactly this problem the same way.

Row separators are off by default. A rule under every row turns a settings page
into a ledger, and the hover fill already marks where a row starts and ends.

Surfaces get vertical gradients, derived from a single theme tone rather than a
hardcoded pair, so they follow whatever the active theme sets. Lerp rather than
a brightness multiplier: these surfaces sit near black, where scaling a channel
of 12 by 1.14 lands back on 13. That is what LerpTowardBlack is for.

The selected segment finally uses DrawSlipPolygon, which has been sitting in the
plugin unused since it was written, and its highlight is a second, shorter
chamfer rather than a clipped gradient -- PushClipRect is rectangular and would
have squared the cut corner straight back off.

Reference note: Lightless and Umbra were read for approach only. Both are
AGPL-3.0 and none of their code is here; a vertical gradient is common
knowledge, their implementation of it is theirs.
2026-08-18 17:42:02 +02:00
JonKazama-Hellion 2f4518a6b1 fix(style): give the settings pane the contrast it was missing
The converted tab had the right structure and no legibility. Five separate
causes, all of them contrast rather than colour choice.

The content pane never set ChildBg, so it inherited whatever showed through the
window, and the window is translucent by default. Settings text was sitting on
moving scenery. It gets the surface tone now; the window's own opacity still
applies on top, so the glass look survives.

Section headings had no ground of their own and floated between the rows at
roughly their weight, which meant the tab had lost its grouping entirely. They
get the raised surface, and their accent bar now runs the full height instead of
stopping at the title line.

An off toggle was filled with the same surface tone as the row behind it and
read as empty space. It gets an outline that fades out as it turns on, where the
filled track carries the shape by itself.

Two colours could not be picked statically at all, because themes here range
from near-black to pastel: the label on a selected segment, and the knob on the
track. Both now derive from the luminance of what they sit on, so neither can
end up light-on-light. That is what ColourUtil.OnColour is for.

Descriptions drop from TextMuted to TextFaint. Level with the label they made
each row read as two settings rather than one with an explanation.
2026-08-18 17:13:43 +02:00
JonKazama-Hellion 5a4c3b6707 feat(settings): convert the window tab to the styled widgets
The first tab that actually looks different. Everything here was stock ImGui:
framed collapsing bars, checkboxes with the label trailing on the right, and
sliders glued to the left edge with their name behind them.

Now: section headers with an accent bar, rows with the label on the left and the
control right-aligned in its own column, sliding switches instead of checkboxes,
and a segmented control where two radio buttons used to pretend to be two
settings when they are one.

Three of the four widgets built in this cycle had no call site outside the debug
gallery. That is the exact defect that triggered v1.10.0 -- five tools built and
never wired up -- and the spec rule written afterwards says no widget without a
call site in the same cycle. This closes that on the pilot tab; the remaining
five follow one at a time.

The row helpers live in SettingsWidgets so the other tabs get them unchanged,
and the theme lookups go through SettingsPalette, cached per frame: twenty rows
would otherwise resolve the same five tokens twenty times over.

Section keys are u8 literals rather than the visible titles. ImGui's own storage
keys collapsing headers off the label, which would reset every section's open
state on a language change and merge two sections whose titles translate alike.

Note WindowTab's constructor gained a parameter, so this needs the DI smoke pass
before the next tab follows.
2026-08-18 17:07:39 +02:00
JonKazama-Hellion 18d43f9afa fix(emotes): survive BetterTTV's shared-emote endpoint going private
/emotes/shared/top now answers 403 with {"message":"unauthorized"}. Nothing
checked the status code, so that object was handed to a List<Top100>
deserializer, which threw on the very first character on every plugin start.

The throw escaped the whole loader, so the 65 global emotes -- fetched
successfully one call earlier -- were discarded along with it, and State went
back to Unloaded, arming the same failure for the next trigger.

A failed page now stops paging and keeps what the global endpoint returned. The
global call itself still throws when it fails, because without it there is
nothing to keep.

Two smaller hazards on the same path: an empty page would have made Last() throw
rather than end the loop, and a null deserialization result was dereferenced
outright. Both end the loop now.

Logged as a warning, not an error. This is a third-party endpoint changing its
access policy, not a fault in the plugin, and it does not need a stack trace in
the log at every launch.
2026-08-18 17:01:10 +02:00
JonKazama-Hellion 6397916712 fix(settings): show which channels get their history deleted
Three of the four first-run profiles switch the retention sweep on and write a
per-channel deletion policy. The window only ever showed the global default, so
whatever the wizard decided about individual channels was invisible from the
moment the wizard closed.

The tab now lists every channel whose retention differs from the global value,
tagged by where the number comes from, plus a button to drop the custom ones. It
also finally uses the strings written for this screen, sweep description and
default help included.

Read-only, deliberately. Zero means "keep forever" as a global default and
"delete this channel's entire history" as a per-channel value, because the
default takes a separate SQL branch while a mapped channel gets cutoff = now. No
shipped profile contains a zero and no UI could set one, so nothing is broken
today -- but an editor cannot be offered until those two meanings agree. Noted
at the branch in DeleteByRetentionPolicy.

The default slider now goes down to 0, which is the value that means "never
delete anything". Its own label has been promising "0 = never" while the slider
started at 1.
2026-08-18 14:43:34 +02:00
JonKazama-Hellion 588b886537 fix(settings): remove the switches that do nothing
Six settings had a control, a saved value, translated labels, and no reader
anywhere in the plugin. Flipping them changed a byte on disk and nothing else.

Three sat next to each other in the Chat tab under timestamps, so the section
read as four related options where only one -- the 24-hour clock -- works.
FormatTimestamp consults nothing else.

The first-run wizard offered one of them too, on its visual step, and listed it
back in the summary as if it had been applied. That is the first screen a new
user sees, so it goes as well.

Their own strings show how long this has been drifting: the wizard called
PrettierTimestamps "relative time", the settings tab called the same field
"modern layout". Two different features, one boolean, neither implemented. That
is also why these are removed rather than wired up -- there is no single
behaviour to restore, and inventing one belongs in a cycle that plans it.

Config fields stay, with a comment. A stored value should survive until the
rendering it describes exists, and dropping them would silently reset anyone who
set them.

Found by an audit that turned up considerably more of this: 433 of 824
translated resource keys reach no code at all, and the export, cleanup, tab
editor and pin paths are complete but unreachable. That is its own cycle; this
commit only clears what actively lies to the user in the window we are working
on.
2026-08-18 14:41:07 +02:00
JonKazama-Hellion 64db8986e6 fix(style): close the remaining unreserved-space cases
Three more instances of the pattern the previous fix only half caught.

The section header clipped its description and not its title, so a translated
heading wider than the pane ran out over the scrollbar. Only the window clip
rect stopped it, not the content width.

Row's separator used an unscaled 1px offset with a scaled stroke. ImGui strokes
centred on the path, so at UI scale 2 half the line sits below the rectangle the
row reserved -- and rows stack flush, so it landed in the first pixel row of the
next one. Offset now derives from the thickness.

The segmented control claimed in its own comment to share the setting row's
contract. It did not. It took a position as a parameter and then re-pinned the
layout cursor to it, which moves a caller's layout whenever that position was
not the cursor, and it advanced by the full height where the other two subtract
ItemSpacing.Y. It now reads the cursor like they do, and the comment says why
the advance still differs: those two stack flush because they are list entries,
this is a single control and takes the normal gap.

Also: the label centres against the control band when it has no description
below it, since a slider draws its text at FramePadding.Y and a top-aligned
label sits visibly high next to it. Gallery arrays are held rather than rebuilt
per frame, which its own comment already demanded two sections earlier. And
SectionHeader.Reset is gone -- no caller, and section state keys off ids rather
than labels, so nothing needs to clear it on a language change.
2026-08-18 14:38:42 +02:00
JonKazama-Hellion 0c3023c8cb fix(settings): stop enum combos listing blank rows
The shared label buffer was handed to ImGui.Combo whole, with the value count as
the fourth argument. That argument is not the item count -- it is
popupMaxHeightInItems. The count comes from the span's own length, which was
always 8.

So every enum combo listed eight rows. A three-value setting showed five blank
ones below its real entries, and the popup was capped at three rows high, so it
scrolled. Clicking a blank row hit the range guard and silently did nothing.

Five combos were affected: world suffix, name form, command help side, preview
position and tell auto-open mode. The per-tab code this replaced sized its array
to the value count, so the count happened to be right; sharing one buffer is
what exposed the misread parameter.

Slicing the buffer fixes both halves at once: the span carries the real count
and popupMaxHeightInItems falls back to its -1 default.

Also moves Lerp below LerpTowardWhite. It was inserted directly under that
method's comment block, TEST-MIRROR line included, so the documentation sat on
the wrong method.
2026-08-18 14:11:31 +02:00
JonKazama-Hellion c5a0c4d0d7 fix(settings): show the translations the channels tab already had
Twenty resource keys existed, were translated into all 25 languages, and were
reachable from no line of code. The tab drew hardcoded English literals instead,
so a German player read "Enable auto-tell tabs" while the German string sat in
the plugin unused. This is the same defect as the three unreachable settings
earlier in this cycle, one level down: the work was done, the wiring was not.

The literals were also worse than the strings they shadowed. "Enable auto-tell
tabs" against "Automatically open a tab per conversation partner for every
/tell", and every setting had a written description that had never been shown at
all, so nothing in the section explained what it did.

Two of those are worth more than the labels. The conflict hint names the one
setting in another plugin that silently stops auto-tell tabs from ever opening,
which is not something a user works out alone; it is on screen now. The sidebar
width description explains what the 44px default actually means.

The keys carry stale prefixes from the old eight-tab layout -- the preload one
still says Privacy_ though the setting lives here. Renaming them would touch 25
files per key, so they keep their names and the strings go on screen now.
2026-08-18 13:54:01 +02:00
JonKazama-Hellion 1c78a84b9b fix(style): reserve the height a wrapped description actually needs
Both widgets drew their description with a wrap width and then sized the row as
if it were always one line. Same bug, two different symptoms.

A setting row clips to its label column, so the second line was simply cut off,
directly under a comment claiming the text wraps rather than being cut. A
section header has no clip rect at all, so the overflow was drawn over its own
border line and into whatever the caller rendered next.

Both now measure with CalcTextSize against the same wrap width they draw with.
The section header also gained the clip rect it never had, and its lead offset
is computed once instead of twice, so the measured width and the drawn width
cannot drift apart.

Third fix, same family: the segmented control relied on its last InvisibleButton
to leave the cursor in the right place. It happened to work, because the loop
re-pins the cursor before every segment, but a caller cannot see that from the
outside -- and the gallery duly reserved the row a second time with Dummy,
doubling the gap after every segmented control. The widget now owns its advance
explicitly, like the other two, and CalcSize is gone with its only caller.
2026-08-18 13:53:51 +02:00
JonKazama-Hellion f999036e50 refactor(settings): merge the duplicated tab helpers
Six tabs carried a byte-identical DrawToggle, four a byte-identical slider, and
five hand-rolled the same enum combo loop. 281 lines out, 82 in.

The combos were not only duplicated, they were wasteful: each one called
Enum.GetValues inside Draw, so every open settings window allocated five arrays
per frame for sets that cannot change at runtime. EnumValues<T> reads them once
per closed generic, and the label array is one buffer shared by all of them.

Two behaviours are now uniform rather than accidental. The range check on the
selected index existed in exactly one of the five and is now in all of them,
and the tell auto-open combo lost its inline literal array in favour of a Name
extension like its seven peers -- still English, but at least in the place the
localisation pass will look.

SettingsWidgets is constructed by each tab rather than injected. The tabs are DI
singletons and a seventh constructor signature change buys nothing here.

One visible difference: the tell auto-open combo was 220px wide against 200 for
every other combo in the window. It is 200 now.
2026-08-18 13:42:21 +02:00
JonKazama-Hellion fa15130468 feat(style): let a setting row render disabled
Six settings across the window only apply while another one is on. Today they
sit at full contrast and simply do nothing when clicked.

BeginDisabled cannot carry this: it pushes an alpha that ImGui applies inside
its own widgets, and every part of a setting row that a user reads -- label,
description, separator, hover fill -- is draw-list output that never sees it.
So the row fades itself, drops its click, and stops tracking hover.

The flag is passed through to the control callback as well. A draw-list control
handed into the row has exactly the same problem and no other way to learn about
it.

Note the parameter sits before styleOverride, so the one existing positional
call site had to name its argument.
2026-08-18 13:37:43 +02:00
JonKazama-Hellion 688c05cd77 feat(style): add the segmented control
WindowTab picks its layout with two radio buttons that are one setting wearing
two labels. A setting row knows one label and one control, so the choice was
either two rows that misstate the relationship or a control that holds the whole
choice. This is the latter, and it generalises to any small closed set.

Segment bounds come from rounded edges rather than a per-segment width. At 201
pixels over two segments the naive form paints two 100.5px halves that land on
the same physical column, which leaves a seam in the middle and a gap on the
right. Deriving each edge from the run means segment i ends exactly where i+1
starts.

Hover keys are derived per segment for the same reason the toggle derives its
own: the caller has already spent its id on the enclosing row, and sharing it
would tie the row highlight to whichever segment the mouse is over.

Disabled is a parameter rather than a BeginDisabled scope because that alpha
never reaches draw-list output. The invisible buttons are still submitted while
disabled so item count and cursor advance do not change between the two states.

MetricsMath gains Center, which is what CenterY always was underneath. Reusing
CenterY to centre text horizontally would have read as a bug at every call site.
2026-08-18 13:37:43 +02:00
JonKazama-Hellion cade398b4e feat(style): add the collapsible section header widget
Replaces ImGui.CollapsingHeader, whose framed bar is the single most
ImGui-looking element in the settings window -- 25 of them across nine files.

State lives in the widget, not in ImGui's per-window storage. ImGui keys that
off the label, so once the section titles are localised the open/closed state
would reset on every language switch, and two titles that translate to the same
string would share one state. Callers pass a stable key built from an ASCII
literal instead.

The disabled parameter is not optional decoration. BeginDisabled pushes an
alpha that only reaches ImGui's own widgets, so a draw-list header would sit at
full opacity while everything around it fades -- and ThemePicker wraps two of
its headers in exactly that.

Cursor advance goes through ImGuiP.ItemSize like SettingRow, so the scrollbar
sees the full height.

The gallery shows all three states, including the disabled one inside a real
ImRaii.Disabled scope, which is where the alpha problem would otherwise only
surface in the theme picker.
2026-08-18 12:01:12 +02:00
JonKazama-Hellion cbc4b17e1e fix(style): make the setting row usable for the widgets that need it most
Review of the two new widgets found four things that would all have landed on
the first real tab.

SettingRow had no hit area and no return value, so "the whole row is clickable,
label included" -- which is the point of pairing it with a switch -- was not
reachable. The label half is now an InvisibleButton and Draw returns whether it
was clicked.

SetNextItemWidth is a silent no-op for Checkbox, RadioButton and
InvisibleButton: they size themselves from GetFrameHeight and never call
CalcItemWidth. So exactly the controls the settings tabs are full of would have
sat at the left edge of the control column, 200px from where the row promised
to put them. The callback now receives a context with AlignRight for widgets
that know their own size.

The switch and the row shared a HoverState key. An enabled switch would have
kept its row permanently highlighted, and hovering a disabled row would have
slid its knob to "on" -- the widget lying about its own value. ToggleSwitch
derives its animation key now, so a caller cannot collide even by passing the
same id to both.

The cursor advance moves from SetCursorScreenPos to ImGuiP.ItemSize. Both
advance the cursor, but only ItemSize is guaranteed to extend CursorMaxPos,
which is what the scrollbar measures. SetCursorScreenPos happens to do it on
ImGui 1.88, which is what Dalamud ships -- upstream removed that in 1.92 and
asserts on the pattern instead. ItemSize does not touch g.LastItemData, so the
save throttles stay intact.

Two smaller ones: the label column no longer collapses to a single pixel on a
narrow row (it stops at 60 and the control shrinks instead), and the toggle
geometry clamps its radius once rather than deriving travel from an unclamped
value. Descriptions wrap now instead of being cut at the column edge.

The gallery gained the pairing both widgets exist for, plus a style-override
variant -- the combination that would have exposed all of this.
2026-08-18 11:59:52 +02:00
JonKazama-Hellion 86992c70f2 feat(style): add the setting-row and toggle-switch widgets
Two composites for the settings window, both built on the primitives from
v1.10.0 rather than beside them.

SettingRow puts the label left and the control right-aligned. ImGui does it the
other way round, control first and label trailing, which is a large part of why
the settings window reads as a form dump rather than a settings page. The
control arrives as a callback so one row covers toggles, sliders, combos and
buttons.

The cursor advance in SettingRow is the part that needed care. It has to happen
after the callback, because ItemSize overwrites CursorPos outright when the
control is submitted -- advancing first would simply be undone. But it must not
be an ImGui.Dummy: that submits an item and would replace the control as
g.LastItemData, silently disabling every IsItemDeactivatedAfterEdit save
throttle in the window. SetCursorScreenPos moves the cursor without touching
last-item state.

ToggleSwitch is a capsule with a gliding knob, driven by HoverState so it
animates instead of snapping. Unlike a slider there is no throttle to preserve:
a checkbox commits on the click itself. The caller owns the hit area, so a
settings row can make the whole row clickable, label included.

Named ToggleSwitch, not Toggle: Dalamud's Window base class already has a
Toggle() method, and the plain name collides in every window that uses the
widget.

Geometry lives in WidgetGeometry as usual, with nine new cases pinning the
right-alignment split, the narrow-row fallback (the label yields before the
control does), and that the knob stays inside its capsule at both ends.
ColourUtil gains a two-colour Lerp for the track crossfade.
2026-08-18 11:37:11 +02:00
JonKazama-Hellion 5b51f7dcfd fix(settings): use the existing translations and unfreeze the window title
Review of block A found three things a German user sees straight away.

Two of the three new controls hard-coded English labels although translated
resources already existed for exactly them: Options_PlaySounds_Name and
Options_KeybindMode_Name are in all 25 files. So "Sprache" sat directly above
"Play sounds". The help marker now uses Options_PlaySounds_Description too.

The settings window title was baked in at construction, so it kept whatever
language the plugin started in. Every other string re-reads per draw; this was
the one frozen one. A PreDraw override refreshes it.

Three smaller items from the same review:

The comment on the language order was wrong in both halves. None never reaches
the sort -- it is filtered out and pinned to the front -- so the "list would
jump" hazard it described cannot happen, and the count was 25 endonyms, not 24.
Left as-is it invited someone to swap Where and OrderBy, which would make the
order depend on the culture the game started in.

The rebuild comment claimed thread affinity made it safe. It does not: the
rebuild disposes the very font handle that Plugin.Draw has pushed for the
frame. It works because Dalamud holds the ImFont under a per-frame lock, and
that is now what the comment says. The help marker also warns that switching
rebuilds the atlas and where to clear accumulated glyph ranges.

ApplyLanguage gets an equality guard. Combo only reports real changes, but a
font atlas rebuild is expensive enough that no future caller should be able to
trigger a no-op one.

ChatTab lost its last ChatType reference with the deleted grid, so the using
went too.
2026-08-18 11:33:42 +02:00
JonKazama-Hellion 9a31bbba03 feat(settings): bring back three settings that had no way to reach them
All three drive real behaviour and have translated labels in all 25 language
files. None of them had a control anywhere in the UI -- they were lost in the
v1.6.0 window rewrite and nobody noticed, because the config kept working with
whatever value happened to be stored.

Language picker. This is the one that needed care: a combo alone would have
been wrong twice over. LanguageChanged is an instance method, not static, and
its parameter only matters when the override is None -- it reads the config
itself otherwise. Passing picked.Code() there yields "", so "follow Dalamud"
would have silently meant English. Startup gets this right and is copied.

More importantly the glyph ranges. Their activation used to live in
Settings.Apply, a class that has not existed since v1.6.0; the comment at
Plugin.cs:290 still points at it. Without OR-ing the required range in and
rebuilding the font atlas, switching to Korean renders empty boxes until the
plugin reloads. Four steps, in this order, and the order is forced: the culture
switch reads the config, the atlas rebuild reads the glyph ranges.

Sound toggle. Gates both the per-tab notification sounds and the UI click
sound. It even has a self-test, just no switch.

Keybind mode. Strict versus flexible modifier matching. It has Name() and
Tooltip() per value, so it was demonstrably a control in v1.5.6.

The language order is sorted once into a static: 24 of the 25 endonyms are
fixed literals, so the order does not depend on the current culture, and
recomputing it per frame would make the list jump the moment None's own label
changes.

"Show novice network" moves to Behaviour on the way past. It is a display
filter, and it was the only entry under "Notifications" -- which now holds the
sound toggle it was named for.
2026-08-18 11:20:52 +02:00
JonKazama-Hellion 81b68a1681 fix(settings): stop drawing the same privacy options in two tabs
Three settings were rendered in two places at once, and the third is the one
that matters: the entire 89-entry channel grid existed twice. ChatTab's
"Channel filter" section and DataPrivacyTab's "Privacy filter" section wrote
the same HashSet through near-identical code, differing only in the ImGui id
suffix. Whichever one the user found first, the other silently showed the same
state.

ChatTab's section is gone entirely. DataPrivacyTab is a proper superset of it
-- it additionally carries PrivacyPersistUnknownChannels -- so nothing is lost.
PrintChangelog keeps only its General entry, where it belongs: it is start-up
behaviour, not privacy.

The lock-ordering comment moved before the deletion. DataPrivacyTab's version
was "see ChatTab for the ordering", a cross-reference to the file being
removed; the actual reasoning only existed in ChatTab.
2026-08-18 11:19:32 +02:00
JonKazama-Hellion af242db6f6 chore(release): bump assembly version to 1.10.0
Style foundation cycle closed. Smoke tests green across the sidebar, the tab
strip, the status bar, the theme preview and both message densities.

Download links stay on v1.5.6 deliberately: v1.6.0 through v1.10.0 are local
development states and nobody should update into one. The README badge stays
there too, since it points at the published release.

The roadmap now reflects the actual sequence -- the old "next cycle" entry
still named v1.5.7 ad-block, which has been behind the v2.x UI rebuild since
May.

Verified file by file: csproj, repo.json (both assembly versions, links
untouched), CHANGELOG, ROADMAP. Four TODOs remain in the tree, all pre-existing
and none from this cycle.
2026-08-18 10:13:19 +02:00
JonKazama-Hellion 2686a8f74b feat(i18n): localise the quick-button tooltips
The three quick-button tooltips were hard-coded English while the rest of the
UI goes through HellionStrings. All 25 resource files now carry them, machine
translated on Flo's go-ahead.

Verified: every file still parses as XML, and the base file stays English so a
missing language falls back to what was there before.
2026-08-18 10:09:23 +02:00
JonKazama-Hellion 30c495849d fix(ui): stop the context menu crashing and give the quick buttons their tooltips back
Two things Flo hit on the first run.

The context menu threw on EndPopup. The spacing guard added in 929188e was a
`using var`, which disposes at the end of the method -- after EndPopup. ImGui
asserts when a popup closes with a style var still on its stack. The body moved
into a scoped block so the pop happens inside the popup.

The quick-button tooltips were empty boxes. SetTooltip ran inside the
FontAwesome push, and that atlas has no ASCII glyphs, so the text had nothing to
render with. ImRaii.DefaultFont did not save it. The hovered label is collected
now and drawn after the font is popped. Same trap as the unread badge in C5,
different place.

Those three tooltip strings are still hard-coded English while the rest of the
UI is localised. Pre-existing, and adding resources means touching 24 language
files, so it is noted rather than fixed here.
2026-08-18 09:23:12 +02:00
JonKazama-Hellion ca60c851cd fix(settings): read the preview colours from the same tokens as the chrome
The preview still picked its colours by hand: SurfaceHover for the active row
where the sidebar uses SurfaceActive, and a plain surface for the pills where
the status bar uses SurfaceRaised. Since SurfaceActive was just raised from
0.1 to 0.25, the preview showed a noticeably different active row than the one
next to it.

It resolves through TokenResolver now. Copying the lerp formulas is how it
drifted out of sync to begin with.
2026-08-18 00:20:31 +02:00
JonKazama-Hellion d79188c7b0 fix(statusbar): size pills from the text and give every slot a fit check
Review of block E found the pill height locked to its design value.
WidgetGeometry.Pill discarded the measured text height, so a pill was always
22px times display scale -- and Config.FontSizeV2 does not feed into display
scale. At 18pt the 24px line no longer fit its 22px pill, at 20pt the text left
the reserved strip entirely. Both sizes are in the plugin's own font list.

Height is a floor now, and the text plus vertical padding wins when it is
taller. At the default 12.75pt the floor still applies, so nothing moves.

Only the right-hand version slot checked whether it had room. At 150% scaling
with the window at its 480px minimum -- which stays reachable, because the size
constraint is not scaled -- the counts and tells pills simply ran off the edge.
Every slot checks now.

Pill.Draw returns the size it drew, so the status bar no longer measures each
slot twice. That also removes the risk of the drawn and returned widths
drifting apart if a style override ever reaches only one of the two calls, and
it cuts the lock glyph from three font pushes per frame to one. A font push is
not free: it allocates a lock object and queues a deferred dispose.

Smaller items: the version string is built once instead of per frame, the glyph
cache from IconButton is now in Pill as well, and five metrics constants plus
two usings that lost their consumers in E1 and E2 are gone.
2026-08-18 00:19:39 +02:00
JonKazama-Hellion 929188e5eb fix(ui): respect window opacity and keep badges off the icons
Reviews of blocks C and D found five things a user would see immediately.

Row fills ignored the window's own opacity. Theme surfaces are fully opaque,
and GlobalStyleScope zeroes ChildBg below full opacity so WindowBg alone
carries the coverage -- with the default of 0.85 that made the sidebar a solid
block inside a translucent window. Idle rows now draw no fill at all, and the
active and hover fills are scaled by the current window opacity.

The unread badge landed on the tab icon at the default sidebar width of 44px.
Right-aligning it needs roughly 70px for one digit and 90px for three, and the
old placement also subtracted the popout column even when there was no popout
button. It is only drawn where it clears the icon; below that a plain dot takes
over, which is what the sidebar did before this cycle anyway.

The same collision existed in the top-tab strip, worse: the badge sat in the
trailing padding, which is 10px against a badge at least 14px wide, so it
covered the label on every tab that had one. The badge is part of the tab width
now, and vertically centred rather than top-aligned.

The context menu's spacing guard read the pushed zero back out of GetStyle, so
the max never did anything and X stayed at zero -- which is what HelpMarker's
SameLine uses, so the "(?)" clung to its label. It sets both axes outright now.

Section captions had all their padding above them and one pixel below, so with
zero item spacing the next row started immediately under the text.

Three smaller items: the tab icon was centred against the text font's line
height although FontAwesome is a fixed-width handle that ignores
Config.FontSizeV2; IconButton interpolated a label string per button per frame,
now a PushID over a u8 literal; and the alpha scaling that had grown four
copies now goes through ColourUtil.ApplyAlpha everywhere.
2026-08-18 00:11:53 +02:00
JonKazama-Hellion 891f8ac0ec fix(style): make the active surface actually visible
SurfaceActive was Lerp(Surface, Primary, 0.1f), picked when no production code
drew the token. Against the real sidebar it is barely distinguishable from
SurfaceBase, so the active row was identifiable only by its 2px accent bar --
which is not what "the active tab is unmistakable" was supposed to mean.

0.25 keeps it clearly a surface rather than a coloured block, and stays
distinct from SurfaceHover, which is its own theme slot rather than a
derivation.

Worth a look across all themes during the smoke test: the lerp target is
Primary, so themes with a very light primary will move further than the dark
ones.
2026-08-18 00:05:53 +02:00
JonKazama-Hellion bfc61909cf refactor(ui): scale the remaining layout constants
What blocks A to E did not already touch: the honorific header height and its
two offsets, the message list dummy widths, and the quick-button reserve in the
input bar.

The reserve is the one with visible consequences. At 150% the buttons grow with
the font while a fixed 130px column does not, so they stopped fitting.

The honorific offsets are centred rather than scaled. The 8f there was
(30 - 14) / 2 for the old font, structurally the same case as the sidebar: a
scaled constant keeps its mis-centering, a computed one does not.
2026-08-18 00:05:23 +02:00
JonKazama-Hellion 0d6877ddc6 fix(settings): align the theme preview with the real chrome
The preview had been showing surfaces, an accent bar and an unread marker for
months while the real sidebar drew none of them. Now that the sidebar has
caught up, the preview is the one that is wrong -- in two specific ways.

It put the accent bar on row 0 and the raised surface on row 1, so it showed
two half-active rows instead of one active row. Both now sit on row 0, and the
rows get the separator the real ones have.

The unread marker was a 4x4 square. It is a rounded count badge now.

The status bar preview was a separate 20px reimplementation with three coloured
squares and a hard-coded label. It mirrors the pill layout instead, with the
status colours riding along as slot dots so a theme still shows what it does to
them.
2026-08-18 00:04:00 +02:00
JonKazama-Hellion a7ed8e1146 feat(statusbar): render slots as pills
Five slots drawn as flowing text with a TextDisabled interpunct between them.
They are pills now: channel with its status dot, privacy with its lock glyph,
counts, tells, and version right-aligned.

The composite texts stay composite. FormatCounts produces "5 tabs · 1.2k msg"
and the version slot "v1.10.0 · Hellion" as single strings, and splitting them
would have gained nothing while breaking their pinned format.

Height derives from the pill rather than sitting beside it as a second
constant. MainWindow reserves the body against this property, so the two
drifting apart is the entire failure mode here, and a pill is taller than a
bare text line.

The right-hand slot's fit check actually measures now. The old one compared the
region against a flat 200px and never looked at the left-hand slots at all, so
at the 480px minimum width it kept drawing the version while the left run
needed more room than was left -- the overlap predates this change.

Pill grew optional icon support for the privacy lock. Without it that glyph
would have been silently dropped in the move.

StatusBarCacheTests is re-enabled. It sat in the csproj Compile Remove block,
so the format contract this commit reshapes around had no live net at all. Two
of its cases construct StatusBar with null services, which is safe because
SnapshotForTest touches neither.
2026-08-18 00:02:55 +02:00
JonKazama-Hellion f2dd49e454 refactor(input): move the channel pill onto the pill widget
The pill was already hand-drawn here -- filled rect, rounding 6, a frozen 3px
text offset and an InvisibleButton over the top. That is the Pill widget, built
before the widget existed, so it becomes the widget's first consumer. Its text
now centres against the measured line height instead of the frozen offset.

InputBar.Height moves to Metrics as well. MainWindow and ChannelPopoutWindow
both reserve their body height against it, so both follow without changes. It
had to happen in the same commit: the pill inside the bar now scales, and a bar
that did not would have clipped it at 150%.
2026-08-18 00:00:15 +02:00
JonKazama-Hellion 918cdc8111 fix(style): stop the hover registry from churning on idle rows
Review of block B found Query allocating an entry for every element it was
asked about, hovered or not. The cycle: Query creates the entry, the next
BeginFrame steps it to zero, evicts it, and the next Query creates it again.
With fifteen tabs that is fifteen allocations plus fifteen dictionary inserts
and removes per frame, permanently, with the mouse nowhere near the window.

That is exactly the property master spec 7.5 asks for and the one this block
claimed to improve, so it ate the two string allocations 31fa410 had just
saved. An unhovered element with no entry now returns zero without creating
one.

The footprint self-test only ever queried with hovered: true, which is why it
could not see this. It now runs an idle phase as well.

Four smaller items from the same review:

Advance skipped clearing the hover flags when deltaTime was zero, so such a
frame carried the previous frame's state forward.

Metrics reads GlobalScaleSafe now. The unsafe variant throws while the
interface manager is still coming up, and block F pulls Metrics into more call
sites.

Badge.CalcSize returned a full-size box for a count of zero while Draw drew
nothing, so a caller that reserves and then draws left a badge-shaped hole on
every tab without unread messages -- the normal case.

IconButton caches its glyph strings; ToIconString allocates on every call and
keeps no cache of its own. And the widget gallery clamps its own row width,
since asserting on a zero-width button in the window that demonstrates the
clamp would be a poor look.
2026-08-17 23:59:17 +02:00
JonKazama-Hellion 5696eac55a test(selftest): pin the top-tab underline invariant
TopTabBar had no observability at all -- no counter, no self-test reaching it.
It now exposes LastRenderedUnderlineCount and MainWindow hands the component
out the same way it already does for the sidebar.

Three cases: one of two tabs active draws exactly one underline, a null active
tab draws zero, and an active tab that is not in the list also draws zero. The
last one matters because the strip skips popped-out tabs, so the active tab
legitimately need not be among the drawn ones.
2026-08-17 23:57:11 +02:00
JonKazama-Hellion e4659bc597 feat(toptabs): draw tabs with an active underline instead of selectables
The strip was ImGui.Selectable sized to the bare text width, with a red dot
hanging off the item rect. Six things had to be rebuilt by hand, and the first
is the one that mattered most.

Selectable did have an active fill (ImGuiCol.Header, fed from the theme), so
this replaces a fill rather than adding a marker to something bare. The fill
stays and the accent underline comes on top -- swapping one for the other would
have made the active tab harder to spot.

Tabs now have their own height derived from the measured line height plus
padding, so the strip no longer collapses onto the text. Hover runs through
HoverState like the sidebar, and the label has three states: active and hovered
in Text, idle in TextMuted.

The unread marker is a count badge in AccentEmber, and its position had to be
recomputed: Selectable inflated its bounding box by half the item spacing on
every side, so reusing the old GetItemRectMin/Max maths against an
InvisibleButton would have made the marker jump.

Click semantics follow InvisibleButton's return value, which fires on release
like Selectable did. IsItemClicked would have fired on press, a silent
behaviour change.

The trailing Separator becomes a LineDivider, so both layout modes draw the
same rule.
2026-08-17 23:56:29 +02:00
JonKazama-Hellion 5caa266287 test(selftest): pin the sidebar active-surface invariant
Drives the real Sidebar.Draw and reads the render counter, so a regression in
the draw path fails instead of a parallel calculation passing.

Three cases: one of two tabs active draws exactly one surface, a null active
tab draws zero, and icon-only mode still marks the active row.

Zero is a legitimate state, not a failure -- PickMainActiveTab returns null
when every tab is popped out, so the invariant is "at most one", not "exactly
one".
2026-08-17 23:54:13 +02:00
JonKazama-Hellion 9936638bb3 feat(sidebar): show unread counts as accent badges
The unread marker was a 4px dot in StatusDanger. Red reads as an error, and an
unread message is not one. It is now a count badge in AccentEmber, which is
what the theme preview in settings has always shown.

It has to be drawn outside the FontAwesome scope: that atlas carries no ASCII
digits, so the number would have come out blank inside it. The icon width is
still measured inside the scope and handed out.

Placement follows the mode. Expanded puts the badge right-aligned ahead of the
popout slot, where a three-digit count still fits; icon-only keeps it over the
icon like the old dot.

The frozen vertical offsets go at the same time. The 8f was (32 - 16) / 2 for a
16px font and stayed wrong at every other Config.FontSizeV2, which display
scaling does not feed into. Both the icon and the label now centre against the
measured line height, and the label starts after the measured icon width
instead of a hard 32f.
2026-08-17 23:53:30 +02:00
JonKazama-Hellion 293d56bdbe refactor(sidebar): move popout and greeted toggles onto the icon-button widget
Both were hand-rolled: an InvisibleButton, then a glyph pushed through the
FontAwesome handle onto the draw list, with a frozen 8px vertical offset and a
4px inset. IconButton does the hit area, the hover fill and the centred glyph,
and centres against the measured line height instead of the frozen offset.

Their order is unchanged. Both still sit after TabContextMenu.Draw, which is
the ordering the popup trigger depends on, and the caller keeps what actually
differs between them: cursor placement (SameLine vs. absolute), the visibility
rule, the glyph choice and the greeted glyph counter that
SidebarGreetedGlyphStep pins.

The popout glyph now follows the row surface rather than rowHovered ||
popHovered. That pair needed the button's own hover state one line before it
existed, and the button sits inside the row anyway, so the row's hover covers
both cases.
2026-08-17 23:52:07 +02:00
JonKazama-Hellion eacefb355d feat(sidebar): draw row surfaces, accent bar and separators
The sidebar drew a hover sweep, an icon and a label per row and nothing else.
No hover fill, no active fill, no accent bar, no separator -- the active tab
was visually indistinguishable from the rest. The theme preview in settings has
been showing all of it for months without the real sidebar delivering any.

Rows now go through the Row widget: base surface, active surface, hover
interpolated between them, a 2px accent bar on the active row and a bottom
separator.

Hover is detected with IsMouseHoveringRect, not IsItemHovered. The row button
is up to two hit widths narrower than the row itself (popout slot, greeted
slot), so a full-width surface driven by the item would flicker at the edges.
AllowWhenBlockedByActiveItem is required on the window check, otherwise the
fill disappears the moment the button is pressed, because InvisibleButton owns
the active id by then.

ItemSpacing is pushed to zero around the row loop so surfaces sit flush instead
of leaving a stripe of window background between them. Style vars are a global
stack and the context menu inherits them, so TabContextMenu now restores a
normal spacing inside its popup -- without that its entries would touch.

The row surface is drawn strictly with draw-list calls between the row button
and TabContextMenu.Draw, which is the ordering the popup trigger depends on.
2026-08-17 23:50:52 +02:00
JonKazama-Hellion 464bd52887 refactor(sidebar): move section headers onto the divider widget
Separator plus TextDisabled took all of their vertical breathing room from
ItemSpacing. The next task pushes ItemSpacing to zero so rows sit flush, which
would have collapsed the header onto its neighbours.

LineDivider carries its own padding and submits its own layout item, so it no
longer depends on the surrounding spacing at all. The compact branch keeps
suppressing only the caption, and LastDrawnSectionHeaderCount still increments
exactly where the caption is drawn -- SidebarSectionHeaderStep pins it at 2
with compact off and 0 with compact on.
2026-08-17 23:49:15 +02:00
JonKazama-Hellion 1e8a60ac80 fix(sidebar): scale the drawn width without moving the stored value
The sidebar constants were raw pixels. At 150% display scaling the text grows,
the column does not, and the row contents stop fitting.

GetWidth and IsExpanded stay unscaled on purpose. The stored width and the
switch threshold are user settings in design pixels, and
SidebarModeAutoSwitchStep compares GetWidth's return value against the raw
bounds with exact equality -- scaling there would fail the step at anything
other than 100%. Scaling happens once, at the single draw call site.

RowHeight and the two hit widths now come from Metrics. The row internals read
GetContentRegionAvail, so they follow automatically and the hit-area split
thresholds stay proportional.

The not-ready branch is scaled too: a scale change triggers a font rebuild, so
that branch really is hit while GlobalScale is moving, and an unscaled width
there makes the sidebar jump.

The width slider referenced the bounds as literals. It now uses the constants,
so it cannot drift away from the clamp.

Known remainder, deliberate: SidebarAutoSwitchThresholdPx is compared against
real screen pixels while the columns now scale, so the switch point drifts at
high scaling. Scaling it would fail the same SelfTest. Noted for v1.11.0.
2026-08-17 23:48:36 +02:00
JonKazama-Hellion 10b345821f fix(messages): apply density switches immediately, freeze the cache while waiting
Review of block A found two regressions the settle gate introduced.

Density and the two name modes are switches, not sliders. They land on a new
value in one frame and stay there, but the gate made them wait 200ms like a
drag. Meanwhile the row painter switched instantly, so for about twelve frames
the planner ran compact rows against card heights: wrong slice, wrong offset,
and the visible rows got overwritten with the new density while everything
else kept the old one. Before the gate this was correct, so it was a
regression, not a pre-existing bug. The fingerprint now separates a discrete
axis that applies at once from the continuous one that waits.

Second, the cache did not actually stand still during the wait. Measurements
were written back unconditionally, so a resize drag mixed heights from many
different widths and the lead dummy drifted for the whole drag. The gate now
exposes IsPending and the planned path skips the write while it is set. The
linear path still measures, because without a filled cache there is nothing to
plan against.

Three smaller items from the same review:

An oscillation slower than the settle window used to bypass the wait entirely,
because the pending clock was never reset on the way back to the applied value.

A value that changes on every frame could hold the gate shut forever while the
applied fingerprint stayed wrong. MaxWaitMs is the deadline, checked before the
still-moving branch so a permanently moving value actually reaches it.

The row painter was passed as `compact ? DrawCompactRow : DrawCardRow`. Both
are instance methods, so the method group captures `this` and Roslyn does not
cache it: 64 bytes per frame per window. Bound once in the constructor now. The
per-frame height array is also reused rather than reallocated, which at the
default MaxLinesToRender was 10 KB per frame on what A2 had just made the
default path.
2026-08-17 23:46:43 +02:00
JonKazama-Hellion 460217459c chore(style): add a widget gallery for visual verification
Every widget in its states, reachable via /hellion widgets. The point is to
check them one at a time before they land in real components: the v2.x style
engine grew three primitives that were never wired to a call site
(DrawGlowBorder, DrawSlipPolygon, DrawHonorificHeader), and this is the cheap
way to notice that before a cycle closes.

DEBUG-only, like SeStringDebugger. It is a verification aid, not a feature, so
it never reaches a release build -- verified against a Release compile.

The header line also shows the live GlobalScale and the hover registry size,
which makes both the scaling work and the eviction contract observable while
dragging the Dalamud scale slider.
2026-08-17 23:42:05 +02:00
JonKazama-Hellion d6ad81e8ca feat(style): add the drawn-widget set
Five widgets, each with a real consumer inside this cycle: Row for sidebar
rows, Badge for unread counts, IconButton for the popout and greeted toggles,
LineDivider for section headers, Pill for the channel pill and the status bar.

Row carries no Tab on purpose. v1.11.0 moves the sidebar from tab rows to
channel rows, and if the chrome sits in a Tab-free widget that cycle only has
to change the caller.

IconButton is deliberately small. Its two sidebar call sites differ in
placement, visibility rule, glyph choice, and one of them bumps a SelfTest
counter. Taking all of that as parameters would produce a widget that is five
switches and no behaviour, so the caller keeps them.

LineDivider brings its own vertical padding and submits its own layout item.
The sidebar is about to push ItemSpacing to zero so rows sit flush, and a
divider relying on spacing would collapse onto its neighbours there.

Colours go through WidgetPalette. TokenResolver returns RGBA and ImDrawList
expects ABGR; with five widgets that is the same swap-red-and-blue trap five
times over.

Sizes go through WidgetGeometry, which is pure so the build suite can pin it,
and clamps every result to a positive extent -- ImGui asserts on a zero-sized
InvisibleButton and takes the window with it.
2026-08-17 23:40:15 +02:00
JonKazama-Hellion 31fa410875 fix(style): drive the hover sheen from held state, drop the leaking start map
The sheen kept its own Dictionary<string, DateTime> of start timestamps and
only cleared an entry in the un-hover branch. A row that disappeared while the
pointer was on it left its entry behind until the plugin reloaded, which is
exactly what happens to temp tabs under the LRU limit.

It now takes the held intensity from HoverState and draws on the rising edge
only. The alpha falls off as the value climbs, so the sweep has faded out by
the time the surface underneath is fully in. On the way out it simply does not
run, which is what stops it from travelling backwards -- the old
SheenStarts.Remove prevented that by resetting, and dropping the map without
this guard would have reintroduced it.

The sidebar call site built "sidebar.tab.{guid}" per row per frame, two
allocations each. Master spec 5.3 asks for constant keys, and 7.5 for a stable
allocation count. It now uses ImGui.GetID("row"u8), which is allocation-free
and seeded from the window's ID stack, so the same literal stays distinct per
window and per PushID'd tab.

HoverSheenAllocStep pinned the old dictionary contract and is replaced by
HoverStateFootprintStep, which pins the same property against the registry:
repeated queries add no entries, and an element that stops being queried leaves
the map instead of leaking.
2026-08-17 23:37:24 +02:00
JonKazama-Hellion bf0c3e2bd7 feat(style): hold hover state across frames instead of one-shot sweeps
DrawHoverSheen measured its own elapsed time against DateTime.UtcNow and gave
up after 0.65s, so a row stopped reacting while the pointer was still on it.
There was no held value to interpolate colours against.

HoverState keeps one 0..1 intensity per element, rising at 14/s and falling at
8/s. Slower out than in is what makes the fade read as deliberate.

Query and advance are separate on purpose. Several SelfTest steps call
Sidebar.Draw against the live tab list, so the same element gets submitted up
to three times in one frame, twice from a window the mouse is not over. If the
query advanced the value, the last caller would win and the fade would run
backwards. Query only ORs the hover flag; BeginFrame does all the moving and
the eviction.

BeginFrame sits above the HideInLoadingScreens and New Game+ early returns, so
a hidden main window still lets pop-out hovers fade out instead of freezing
mid-blend.

FrameLerp gains Ramp: Smooth approaches asymptotically and never arrives, so a
value driven by it would never reach zero and never become evictable.

ReduceMotion short-circuits before the map is touched, returning a hard 0 or 1.
An infinite rate would produce NaN and poison the entry for the session.
2026-08-17 23:35:54 +02:00
JonKazama-Hellion 28b97b3f70 feat(style): add a scale-aware metrics layer
Layout constants lived as bare floats in the components: row heights, hit
widths, insets, reserve widths. None of them multiplied by GlobalScale, so at
125% or 150% display scaling the text grows and the boxes do not. The quick
buttons stop fitting into their 130px column.

Metrics holds the design values and exposes scaled properties. The Raw
constants stay reachable for the few places that must store or compare an
unscaled value: Sidebar.GetWidth (a SelfTest pins it against raw numbers) and
the width slider bounds.

Scale is pinned once per frame against ImGui.GetFrameCount(). GlobalScale is a
live value the Dalamud slider moves on every dragged frame, so reading it per
access can shift a CalcSize away from its matching Draw inside one frame, and
costs three native calls each time.

Not in ThemeLayout: that record is serialised into theme JSON, and layout
customisation is out of scope per the master spec.

MetricsMath is the pure half so the build suite can pin the arithmetic. Text
heights are measured rather than scaled -- the font is built from
Config.FontSizeV2, which GlobalScale does not feed into.
2026-08-17 23:34:08 +02:00
JonKazama-Hellion 0ef33934a2 refactor(messages): plan compact rows like cards instead of assuming a fixed height
Compact mode ran an ImGuiListClipper with CompactRowHeight = 18f. Two things
were wrong with that.

The number: at the default 12.75pt the font is 17px, and ChunkRenderer pushes
ItemSpacing to zero for the whole chunk loop, so a single-line compact row
advances the cursor by 17, not 18. The clipper seeded the cursor one pixel too
low per row, which accumulates into a visible drift against the scrollbar.

The assumption: compact rows are not constant height at all. DrawCompactRow
renders content with wrap: true, and WrapEncodedLine submits one text item per
wrapped line. At 620px and 17px type that kicks in around 70 characters, so
most chat lines are multi-line.

Both densities now share DrawRows/DrawLinearAndMeasure over the existing
CardClipPlanner, with the row painter passed in. The fixed height and the
clipper are gone.

Also corrects the CompensatedDummy comment: the cached heights carry no
trailing ItemSpacing (every row ends inside DrawChunks, where spacing is
zero, and ImGui writes the advance at submission). The compensation is
correct because it cancels the spacing the dummy itself appends.

CardClipPlanStep drives the invalidation hook directly, which now sits behind
the settle gate, so it walks a synthetic clock past the window.
2026-08-17 23:32:04 +02:00
JonKazama-Hellion 39a8e95581 fix(messages): invalidate the height cache when UI scale changes
The layout fingerprint tracked font size, density, both name modes and
content width, but not ImGuiHelpers.GlobalScale. Scale feeds
CalcWordWrapPositionA, so changing it rewraps every row while the cached
heights stay put and the clipper dummies drift against the scrollbar.

Two further problems came out of the same code:

The fingerprint lived in a single field on MessageList while the cache it
guards is per tab. Resizing in tab A marked the new value applied, so tab B
kept measuring against the old width. It is now a gate per tab identifier.

Acting on every fingerprint change is too eager. A window resize or a drag on
the Dalamud UI-scale slider moves the value on every frame, and each change
drops the cache and forces the linear measure path over the whole tab (up to
Config.MaxLinesToRender rows). The gate now waits for the value to settle for
200ms, which turns a drag into one rebuild instead of one per frame.

The settle logic sits in Util/LayoutFingerprint.cs as a plain value type so
the build suite can pin it without standing up an ImGui frame.
2026-08-17 21:17:38 +02:00
JonKazama-Hellion 3583dfc032 perf(tells): build the tab outside the lock, guard pin transitions
HandleTell was one atomic block, and PreloadHistory sat inside it -- so every
new tell partner held TabsListLock across a store query that sorted the whole
receiver history before returning a row. That is the lock the draw thread and
the message worker both wait on.

Now three steps: look for an existing tab under the lock, build the new one
(including history) without it, then commit under the lock again. Splitting it
opens a window where the world can change, so the second block re-checks:

- FindTempTab again, in case something else created the tab meanwhile. The
  message goes to that one instead. Not in the first block's early return --
  HandleTell runs after the delivery loop, so an existing tab already has it and
  adding again would duplicate the line.
- A generation counter, bumped by OnLogout under the same lock. A logout in
  between wipes the unpinned pool, and without this the freshly built tab would
  outlive it and show up for a character we already left. Not via
  CurrentContentId: its getter falls back to a cached value, so the comparison
  can silently pass.
- The pool cap moves into CommitTempTab and stays there exactly once. Evaluating
  it twice would evict a tab on every spawn.

Pin, unpin and promote take the lock around the flag change now -- they decide
pool membership and whether a save strips the tab. SaveConfig stays outside, so
no fsync lands on the click path.

DropOldestTempTab removes by reference: the index came from an earlier Select in
the same block and would point at the wrong tab if anything shifted the list.
2026-08-17 18:38:08 +02:00
JonKazama-Hellion c34024a18b chore(release): bump assembly version to 1.9.0
The whole v1.9.0 cycle ran without a version bump, so the plugin still reported
1.8.8 in-game. For a tester beta that is untenable: bug reports would name a
version that does not identify the code they ran.

Download links stay pinned to v1.5.6 on purpose. There is no v1.9.0 release, and
pointing at an artifact that does not exist is worse than the visible mismatch
between assembly version and download target. Public stays on v1.5.6 until
v2.0.0.
2026-08-17 07:27:59 +02:00
JonKazama-Hellion eaed0b13e0 fix(config): guard the shared config maps, restore lost fields in Tab.Clone
TabsListLock never covered ChatColours, PrivacyPersistChannels or
RetentionPerChannelDays, yet the settings UI mutates them from the draw thread
while the retention thread can be serializing the same config. Adding a new key
to a dictionary or a new element to a set invalidates a running enumeration, so
this could throw from inside JsonConvert.SerializeObject.

Not a corner case: the colour picker lists 66 channels but only 25 ship with a
default, so the first edit of any of the remaining ones inserts a new key -- and
the reset button removes a key, which makes the next edit a fresh insert again.

The readers matter as much as the writers. IsAllowedForStorage runs per message
on the worker thread and asks PrivacyPersistChannels whether a channel may be
stored; a Contains racing an Add that resizes buckets can answer wrong, and that
answer decides whether a message is written to disk. The retention sweep
enumerates RetentionPerChannelDays on the framework thread while the wizard can
clear it -- Clear does not throw there, it just cuts the enumeration short, so
the sweep would run on half a policy.

New ConfigMapsLock covers all of it. It sits inside TabsListLock (that edge is
real, AutoTellTabsService calls SaveConfig while holding the tabs lock), never
the other way round -- so every call site closes the lock before saving.

Tab.Clone silently dropped Icon and ChatCodes, both serialized. A reflection
test now walks the serialized fields so a future one cannot slip past.

Also: CurrentTab read Count and [0] as two separate accesses.
2026-08-17 07:27:48 +02:00
JonKazama-Hellion 2b4243599e fix(ui): render each frame from one tab-list snapshot, key widgets by identity
Sidebar, top tabs and status bar each read Config.Tabs on their own, unlocked,
while the worker added or evicted tabs. That gave three independent views of a
moving list: an index built in one place could resolve to a different tab a few
lines later, which showed up either as an out-of-range crash on the draw thread
or -- worse, because it is silent -- as a click landing in someone else's tell.

MainWindow now takes one snapshot under the lock and passes it through the whole
frame. Deliberately a shallow copy: tab identity is compared by reference all
over the draw path, so cloning would break every ReferenceEquals and Contains.
ChangeTabDelta and ResetActiveTabIfRemoved run on the framework thread and keep
their own locked reads instead; ThemeQuickPicker locks its own copy, since
reaching it would mean threading a parameter through InputBar, which popouts
share and which has no tab list.

Widget IDs move from list position to tab.Identifier. ImGui carries popup and
widget state across frames under that ID, so a position-based one re-binds an
open context menu to a different tab as soon as the list shifts -- a snapshot
cannot fix that, it spans frames. This also resolves top tabs visually merging
into each other when the list changed.

The sidebar section headers counted over the live list while the rows came from
BuildRenderOrder, which skips popped-out tabs. Both sides take the same
predicate now, so the count matches what is drawn.
2026-08-17 07:27:34 +02:00
JonKazama-Hellion 24dff3cc2e fix(messages): snapshot the tab list before delivering a message
ProcessMessage walked Config.Tabs live on the worker thread while SaveConfig's
strip and the auto-tell spawn mutated the same list under TabsListLock. The
resulting "collection was modified" was caught by the pending-message handler
and only logged -- so the message was dropped entirely: no tab entry, no sound,
and MessageProcessed never fired, which also meant no tell tab and no routing.
Silent message loss, exactly under the load where it hurts.

The loop now runs over a snapshot taken under the lock. AddMessage stays
outside it, so the lock order (list outer, MessageList inner) is unchanged.

SelectNotificationSound reports which tab it picked, so playback can skip a tab
that disappeared between snapshot and sound -- otherwise the snapshot would let
an evicted tab still make noise.

While here: the current tab was read twice despite the comment claiming it was
snapshotted once.
2026-08-17 07:27:21 +02:00
JonKazama-Hellion 89c66e0d3d perf(store): index (Receiver, Date) so tell history streams sorted
GetTellHistoryWithSender filters on Receiver and orders by Date DESC. Without a
matching index SQLite sorted the whole receiver history into a temp b-tree
before yielding row one -- measured 10 ms to first row against 9621 tells, all
of it under TabsListLock, which defeats the early break in the caller.

(Receiver, ChatType, Date) does not help: the ChatType IN filter sits between
the equality prefix and the sort column, so the temp b-tree stays. Verified on
a real database: plan now reads SEARCH ... USING INDEX idx_messages_receiver_date
with no sort step.

No SQL LIMIT -- an earlier 500-row cap was removed in v1.4.10 because it cut
less-frequent partners off the back of the window, and 83% of partners have
fewer than 21 tells in total.

The migration dispatcher is cumulative, so Migrate5 is appended to every
existing case, not just the new one.
2026-08-17 06:50:04 +02:00
JonKazama-Hellion d2da51a4f7 perf(settings): write config on release instead of every slider frame
ImGui sliders report a change in every frame the value moves, so dragging one
rewrote the full 31 KB config to disk per frame -- serialize, fsync and rename,
synchronously on the draw thread. Measured on Linux/Wine that showed up as a
114 ms frame while the plugin itself only drew for 2.9 ms; the rest was waiting
on the write.

The five shared slider helpers now defer SaveConfig to IsItemDeactivatedAfterEdit,
matching what ChatColourPicker already did for the colour wheel.

Renaming a tab needed its own path: the input lives inside a popup, and ImGui
never re-submits it when the popup is dismissed by clicking outside, so
IsItemDeactivatedAfterEdit would not fire and the new name would be lost. A
pending-rename marker scoped to the owning tab flushes it when the popup is
gone -- scoped, because every other tab's Draw reaches that branch too.

DeferredSaveFrames is removed: the debounce was fully wired but never armed,
and this approach makes it redundant.
2026-08-17 06:49:53 +02:00
JonKazama-Hellion 99dca8cb31 fix(selftests): take TabsListLock around Config.Tabs mutations
The three sidebar/coupling steps add, insert and remove tabs straight from
the framework thread while the message worker mutates the same list under
TabsListLock. CurrentTabCouplingStep's Insert(0, ...) is the worst of them:
it shifts every index, so DropOldestTempTab can remove the wrong tab between
its index lookup and RemoveAt.

Locks sit around the individual mutations, never around a Draw call, so no
step holds the lock across rendering.
2026-08-17 06:49:42 +02:00
JonKazama-Hellion ce5973aea9 Merge remote-tracking branch 'origin/main' into feature/v1.9.0 2026-08-16 21:08:20 +02:00
JonKazama-Hellion de9d11ba4a docs: v1.9.0 comment-pass (Z-3) — fix false TEST-MIRROR paths, comment accuracy + density 2026-06-16 20:59:09 +02:00
JonKazama-Hellion 618e029ff4 perf(tabs): share Plugin.TabsListLock across AutoTellTabsService + MessageManager refilter + SaveConfig (B3) 2026-06-16 20:39:56 +02:00
JonKazama-Hellion 93f4fbba72 perf(card): variable-height clipper + layout-fingerprint cache invalidation + clip-plan self-test 2026-06-16 20:09:45 +02:00
JonKazama-Hellion 1d69d0cc30 B2: add Dalamud-free CardClipPlanner variable-height clip-plan helper 2026-06-16 19:58:02 +02:00
JonKazama-Hellion b048a51534 B1: dedupe CJK/symbols merge via AddCjkAndSymbols, trim fallback range; FontsReady + report self-test 2026-06-16 19:53:39 +02:00
JonKazama-Hellion 7d2fd1ab65 selftest: add on-disk SelfTestReport log; report PASS/FAIL details from steps 2026-06-16 19:53:39 +02:00
JonKazama-Hellion 2c5c40524d B1: add Dalamud-free CjkFallbackRange helper + coverage tests 2026-06-16 19:25:34 +02:00
JonKazama-Hellion 0508a05bab test(selftest): add GlobalStyleScope GC-reserve alloc probe 2026-06-16 19:23:15 +02:00
JonKazama-Hellion 32013babaf perf(style): make GlobalStyleScope.StackHandle GC-free via counter scope 2026-06-16 19:23:15 +02:00
JonKazama-Hellion 430c8f235a perf(baseline): 1000-frame steady-state capture with quad-proxy draw calls + JSON sink 2026-06-16 19:13:45 +02:00
JonKazama-Hellion 68c4e28495 perf(baseline): time full Draw() handler into LastDrawMs field 2026-06-16 19:13:45 +02:00
JonKazama-Hellion 458df3b4bd Restore permanent-REPLY game-side tell pre-targeting (1.5.6 parity) 2026-06-16 19:03:34 +02:00
JonKazama-Hellion 6733c7f92e Restore pop-out exclusivity: hide popped tabs from main window + keybind/unread parity 2026-06-16 18:30:23 +02:00
JonKazama-Hellion fa20b53455 C2/C3: restore rotation keybinds (REPLY/LS-cycle) + focus contract routing on the focused chat surface 2026-06-16 14:09:28 +02:00
JonKazama-Hellion ea3f00f107 GP-04: reset Tab.PopOut on load via shared helper (clears stale pinned flags) 2026-06-16 13:26:17 +02:00
JonKazama-Hellion 5bdf4217d6 D1-3 (XC-8): route PayloadHandler Send-Tell through shared BuildTellCommand (IsPublic at call-site) 2026-06-16 13:10:22 +02:00
JonKazama-Hellion 97e58934d6 D1 (XC-8): extract shared PrefillTellInput/BuildTellCommand for the two tell-prefill detours 2026-06-16 13:03:26 +02:00
JonKazama-Hellion f05d7104af A3: gate pop-out affordance on expanded sidebar (icon-only overlap fix) 2026-06-16 12:33:26 +02:00
JonKazama-Hellion e98cefa0b2 A2: name Sheen tuning knobs + SmoothStep crossfade easing 2026-06-16 12:29:57 +02:00
JonKazama-Hellion c1765ce8ca A1: harden HoverSheenAllocStep with real dictionary-footprint assertion 2026-06-16 12:22:29 +02:00
JonKazama-Hellion 7ead120213 A1: scharfschalten DrawHoverSheen accent-tint (Variante A) 2026-06-16 12:17:39 +02:00
JonKazama-Hellion f5ba1c0246 A1: add ColourUtil.LerpTowardWhite accent-tint helper 2026-06-16 12:02:53 +02:00
JonKazama-Hellion b372ab84c3 Merge branch 'feature/v1.8.0' into main 2026-06-16 09:18:12 +02:00
JonKazama-Hellion c27785f9f6 Merge branch 'feature/v1.8.0-closeout' into feature/v1.8.0 2026-06-16 09:07:57 +02:00
JonKazama-Hellion 6f71b09331 fix(closeout): address closure-review findings
- gate keybind pill-sync on IsChannelOrExistingLinkshell so an empty
  linkshell slot no longer desyncs the pill from the real send channel
- close manually-popped pop-out windows on logout via an IsOpen filter
  instead of the PopOut flag (which manual pops never set)
- read the router's tell-tab lookup through a lock-wrapped accessor so the
  framework thread cannot enumerate Config.Tabs mid worker-thread mutation
- add a "switch on every tell" toggle (default on) and make the auto-open
  mode pick the matching layout, so Sidebar vs Top-tab are distinct
- comment corrections (stale/contradictory text, TEST-MIRROR path depth)
2026-06-16 09:04:18 +02:00
JonKazama-Hellion 49f5119b17 feat(popout): arm the auto-tell pop-out settings and add the pool self-test 2026-06-16 01:29:59 +02:00
JonKazama-Hellion 6578c10b13 feat(settings): restore the tab-cycle keybind binder UI 2026-06-16 01:21:05 +02:00
JonKazama-Hellion 3878869904 feat(keybind): cycle tabs and switch channel with pill sync 2026-06-16 01:21:05 +02:00
JonKazama-Hellion 88491902eb feat(chat): prefill the input bar for context-menu and direct-chat tells 2026-06-16 01:04:34 +02:00
JonKazama-Hellion 47a49de8c0 feat(tell-router): auto-open incoming tells per TellAutoOpenMode 2026-06-16 00:50:45 +02:00
JonKazama-Hellion 7b6871fea4 feat(autotell): wire temp-tab pop-outs to the channel-popout pool 2026-06-16 00:39:01 +02:00
JonKazama-Hellion 8e2d333130 fix(toptab): size each tab selectable to its label width 2026-06-16 00:24:18 +02:00
JonKazama-Hellion 4db2ad99b9 Merge branch 'feature/v1.8.8' into feature/v1.8.0
v1.8.8 Block 4b -> full theme/window restoration (last of the 1.8.x restore
series). B4b export-button + schema-v2 default-fill, then P1-P8: custom-theme
selection, typography font-size apply, font-selection UI, theme-card mockup,
chat-colour editor, header theme/tab quick-picker, window/display toggles
(title bar, hide button, 24h clock), and hide-window + Enter-to-restore.
Local-only; manifest 1.8.8; all self-tests green.
2026-06-15 21:08:30 +02:00
JonKazama-Hellion a73f4d0d0c feat(window): restore hide-chat-window + Enter-to-restore (1.5.6)
The eye/hide button now hides the HellionChat window (runtime-only, via a new
DrawConditions gate) instead of toggling native-chat suppression, matching 1.5.6.
The chat-activation keybind (Enter / "/"), whose dispatch was a dead stub in the
KeybindManager since the v1.6.0 rewrite, is re-wired to MainWindow.ActivateChat:
it un-hides, opens if closed, brings the window to front and focuses the input --
so the chat reacts to Enter again from any state. /hellion is a reliable one-press
recovery (Toggle now clears the hide), and the window always shows on login
(start state no longer read from the persisted flag). Adds HideRestoreSelfTestStep.
2026-06-15 20:49:14 +02:00
JonKazama-Hellion b397591ba4 feat(window): restore the title-bar, hide-button, and 24-hour-clock toggles
Re-wires four 1.5.6 settings that survived the v1.6.0 rewrite as dormant config
fields but lost their UI + consumers:
- ShowTitleBar / ShowPopOutTitleBar: gate ImGuiWindowFlags.NoTitleBar on the main
  window (ResolveFlags) and pop-out windows (new PreDraw). Inverted logic matches
  1.5.6 (flag set only when the toggle is off).
- ShowHideButton: gate the input-bar hide button on the toggle.
- Use24HourClock: add the toggle (MessageList already consumes the field).
New 'Window style' section in WindowTab; Use24HourClock in ChatTab display modes.
MainWindowFlagsStep extended with the NoTitleBar fresh-base contract.
2026-06-15 20:19:59 +02:00
JonKazama-Hellion 6813b80d58 feat(themes): restore the header theme/tab quick-picker
Brings back the 1.5.4 quick-picker lost in the v1.6.0 rewrite: a palette button
in the input-bar button row (left of the cog) opens a popup that switches the
theme (built-in + custom, active row checked) and jumps between chat tabs without
opening settings. Theme switch mirrors the settings ThemePicker; the tab jump
routes through a new MainWindow.ActivateTab that replays the click path
(previous -> set -> OnTabActivated) so tell/unread handling is unchanged. Main
window only -- pop-out InputBars get a null picker. Adds QuickPickerSelfTestStep.
2026-06-15 19:53:31 +02:00
JonKazama-Hellion 0352e6c199 feat(themes): restore the chat-channel colour editor in the appearance tab
Brings back the 1.5.6 per-channel colour editor lost in the v1.6.0 rewrite:
presets (incl. brand styling), per-ChatType reset/import-from-game/colour-edit
over Config.ChatColours, the colour-selected-input-channel toggle, and the
theme adopt-banner. The colour-edit drag recolours live but defers SaveConfig
to release (IsItemDeactivatedAfterEdit) to avoid a per-frame full-config write.
2026-06-15 19:12:09 +02:00
JonKazama-Hellion 8cbf9c554f feat(themes): restore the per-card theme preview mockup in the picker 2026-06-15 18:49:45 +02:00
JonKazama-Hellion 18834cddae feat(fonts): restore the font-selection UI in the appearance tab 2026-06-15 18:41:03 +02:00
JonKazama-Hellion fe0414dd2b feat(themes): apply theme typography font-size overrides on every activation path 2026-06-15 18:19:08 +02:00
JonKazama-Hellion ec92cf2c04 feat(themes): list custom themes in the theme picker 2026-06-15 18:03:39 +02:00
JonKazama-Hellion 512533ed3a feat(themes): default-fill missing colour/layout slots on theme load 2026-06-15 16:55:50 +02:00
JonKazama-Hellion a2d8a9c223 feat(themes): add an export button for the active theme 2026-06-15 16:55:50 +02:00
JonKazama-Hellion dcf089b886 chore(release): bump manifest to 1.8.8 for theme export, default-fill, font-apply 2026-06-15 16:18:05 +02:00
JonKazama-Hellion c4562dd6a0 style(selftests): wrap HonorificTitleData ctor to satisfy csharpier
Inherited csharpier drift from the 1.8.7 merge (72099c8); format-only, no behaviour change.
2026-06-15 16:18:05 +02:00
JonKazama-Hellion 74f7bb3fc1 Merge branch 'feature/v1.8.7' into feature/v1.8.0 2026-06-15 14:50:02 +02:00
JonKazama-Hellion 8afcb87624 test(about): assert integrations status through the real render 2026-06-15 14:44:26 +02:00
JonKazama-Hellion f9ed487ae2 feat(about): restore the integrations section with honorific status 2026-06-15 14:40:21 +02:00
JonKazama-Hellion 72099c8871 test(honorific): assert the title gate through the real draw path 2026-06-15 14:35:20 +02:00
JonKazama-Hellion fe766285ad feat(honorific): wire title gate + colour + truncation, restore preview glyphs 2026-06-15 14:26:22 +02:00
JonKazama-Hellion 8db2dee38c chore(release): bump manifest to 1.8.7 for honorific + integrations restoration 2026-06-15 13:53:06 +02:00
JonKazama-Hellion a38afbcf67 Merge LastTab-decoupling fix + unread-badge restore (1.8.6) into v1.8.x track 2026-06-13 18:53:28 +02:00
JonKazama-Hellion 5dfe8e3b49 fix(unread): restore the tab unread badge and fix the post-F2 unread decision
The v1.8.x sidebar/top-bar rebuild never re-rendered the unread dot, so inactive tabs showed no badge even though the counter was tracked. Draw it again top-right of the tab icon in both Sidebar and TopTabBar, gated on !active && UnreadMode != None && Unread > 0, and zero the active tab's counter every frame (1.5.6 convention) so the dot only ever shows on tabs you are not looking at.

The unread decision moves to MessageManager.ShouldCountUnread and snapshots the active tab + whether it shows the message once before the loop: Unseen suppresses unread on an inactive tab only when the active (real, post-F2) tab also shows that message. Adds SidebarUnreadDotStep (render) and UnreadDecisionStep (decision) self-tests (step count 32 -> 34).
2026-06-13 18:49:27 +02:00
JonKazama-Hellion 0ca8513065 fix(tell): couple CurrentTab to the active tab, retire LastTab
Plugin.CurrentTab now delegates to MainWindow.ActiveTab (fallback Tabs[0]) instead of the never-assigned LastTab index, so the game hooks, unread tracking, notification sounds, InputDisabled and Foray/Eureka paths all operate on the tab the user actually has selected. The dead LastTab/WantedTab fields and both WantedTab writes are removed.

A reference-based MainWindow.ResetActiveTabIfRemoved repairs the active-tab reference on eviction/logout (immune to the SaveConfig temp-tab strip window). The worker-thread eviction path marshals it onto the framework thread so the strip mutation serializes with Draw; logout is already framework-thread. The Draw-seed gains a lazy re-seed for a wholesale config swap. Adds CurrentTabCouplingStep (headless) and the interactive CurrentTabGuidedStep self-test (step count 30 -> 32).
2026-06-13 16:09:59 +02:00
JonKazama-Hellion ad635c77c1 fix(tell): strip stale tell state on tab activation
OnTabActivated clears the runtime tell state the game-side detour leaves on a tab (CurrentChannel tell target + partner label) when a DIFFERENT tab becomes the input surface, so a normal typed line can no longer route as a silent /tell to the old partner. Re-clicking the active tab and tabs carrying their own Tab.TellTarget binding (leg1) are preserved.

All four activation paths route through it: Sidebar, TopTabBar, ChannelPopoutPool.TryOpen, and the MainWindow draw-seed. EnsureCurrentChannel becomes a pure derive-helper reached only via OnTabActivated. Adds the TellResetOnActivateStep self-test (step count 29 -> 30).
2026-06-13 15:09:38 +02:00
JonKazama-Hellion 593eb30c9f chore(release): bump manifest to 1.8.6
Branch start for the LastTab-Decoupling fix cycle. csproj <Version> and repo.json AssemblyVersion + TestingAssemblyVersion go 1.8.5 -> 1.8.6. DownloadLinks and Changelog stay release-deferred on v1.5.6.
2026-06-13 14:23:10 +02:00
JonKazama-Hellion 11ef5951a4 Merge restoration block 3 (sidebar UI) into v1.8.x track 2026-06-10 17:00:51 +02:00
JonKazama-Hellion c28e3f72a1 feat(messages): restore scroll-to-bottom bar with snap decision 2026-06-10 16:55:26 +02:00
JonKazama-Hellion dc51e295ea feat(sidebar): restore section headers and compact separators 2026-06-10 16:22:49 +02:00
JonKazama-Hellion 540cb7ac52 feat(sidebar): restore per-tab greeted toggle glyph 2026-06-10 14:59:51 +02:00
JonKazama-Hellion 1f2c354471 feat(sidebar): restore per-tab notification sound picker with preview 2026-06-10 13:26:55 +02:00
JonKazama-Hellion ac7f74b227 feat(sidebar): restore tab rename via shared context menu 2026-06-10 11:42:44 +02:00
JonKazama-Hellion c7047407f5 feat(core): add static Plugin.Instance handle for UI helper access 2026-06-10 10:09:32 +02:00
JonKazama-Hellion e5a17ee798 chore(release): bump manifest to 1.8.5 for sidebar-ui restoration 2026-06-10 10:01:55 +02:00
JonKazama-Hellion 83de7cd989 Merge tell-routing restoration (1.8.4) into v1.8.x track 2026-06-04 17:20:59 +02:00
JonKazama-Hellion 51c8f79846 chore(release): bump manifest to 1.8.4 for tell-routing restoration
Download links stay on v1.5.6 (local-only block, no public release yet).
2026-06-04 17:11:32 +02:00
JonKazama-Hellion d40b120b91 fix(tell): restore outgoing tell routing from the input bar
Input-bar tells went out as a bare "/t" without the target, so the game
rejected them with "you must add the World name". Rebuild the full
"/tell name@world" from the 1.5.6 target chain in a pure BuildOutgoing:

- leg2/leg3 gated on current == Tell so a stale tell target on a Say tab
  can't send a say line silently as /tell (CORR-1)
- world-resolve gate: an unresolvable world falls back to the channel
  prefix, never "/tell name@ text" (COMP-1)
- ResetTempChannel after the send, tell-only

Also clear the runtime tell state on PromoteToPermanent so a promoted tab
can't route a typed line to the old partner, and surface the tell partner
("-> name@world") in the channel pill so a misfire stays visible. Adds
tell-routing and pill-transparency self tests.
2026-06-04 17:11:32 +02:00
JonKazama-Hellion e372afc8ac Merge restoration block 2 (settings without UI) into v1.8.x track 2026-05-31 00:48:58 +02:00
JonKazama-Hellion b0bee25770 feat(input): warn and hold before sending plugin-only symbols 2026-05-31 00:45:31 +02:00
JonKazama-Hellion 92f1736ea9 feat(settings): add world suffix and name format combos to the chat tab 2026-05-31 00:36:09 +02:00
JonKazama-Hellion 83b1708d5d feat(messages): render sender names through the name-aware path 2026-05-31 00:31:48 +02:00
JonKazama-Hellion 8fcb10cf51 chore(release): bump manifest to 1.8.3 for restoration block 2 2026-05-31 00:11:29 +02:00
JonKazama-Hellion 71cf6234b5 Merge restoration block 1 (dead settings) into v1.8.x track 2026-05-30 19:08:15 +02:00
JonKazama-Hellion 78d56f0e3e fix(channels): restore auto-tell limit range to 50 and relocate enable toggle 2026-05-30 19:04:32 +02:00
JonKazama-Hellion ca00f528d6 feat(config): drop dead SidebarTabView and migrate false to top tabs (schema v23) 2026-05-30 18:55:26 +02:00
JonKazama-Hellion a7a5aee982 feat(sidebar): wire configurable expanded width through a single source 2026-05-30 18:22:38 +02:00
JonKazama-Hellion caacb87a6a feat(window): wire move/resize flags and consolidate the duplicate toggle 2026-05-30 17:54:15 +02:00
JonKazama-Hellion 336f722eef feat(window): wire inactive opacity to main window focus state 2026-05-30 16:57:59 +02:00
JonKazama-Hellion 7792b327dc chore(release): bump manifest to 1.8.2 for restoration block 1 2026-05-30 16:17:06 +02:00
JonKazama-Hellion 6581943bf1 Merge restoration block 0 (verification truth) into v1.8.x track 2026-05-30 08:56:00 +02:00
JonKazama-Hellion c84891e75d docs(selftest): add binding render-path selftest standard 2026-05-30 08:43:06 +02:00
JonKazama-Hellion 6af9e05664 test(selftest): add PayloadHandler and ChunkRenderer ctor smoke steps 2026-05-30 08:40:51 +02:00
JonKazama-Hellion ea549ebcd0 test(selftest): remove dead ConfigMigrationV21 step superseded by V22 2026-05-30 08:23:29 +02:00
JonKazama-Hellion d33c25e77a chore(release): bump manifest to 1.8.1 for restoration block 0 2026-05-30 08:18:16 +02:00
JonKazama-Hellion ad892cbcb6 feat(layout): add top-tabs layout mode and shared channel resolver 2026-05-29 14:06:41 +02:00
JonKazama-Hellion a9e70ce2af fix(popout): guard against mid-frame unbind when closing from the header 2026-05-29 13:29:29 +02:00
JonKazama-Hellion db47708264 feat(popout): wire pool + window render + sidebar pop-out routing 2026-05-29 12:49:21 +02:00
JonKazama-Hellion e786257cb3 feat(config): add MainWindowLayoutMode + v22 migration; scaffold popout pool 2026-05-29 11:56:18 +02:00
JonKazama-Hellion b221a6e418 feat(input-bar): wire auto-translate tab picker + payload-replace on send
v1.7.0 component-layer refactor removed ChatLogWindow.cs (which housed
the auto-translate popup) and dropped Ui/AutoCompleteInfo.cs without
migrating the logic into the new InputBar component — v2.x spec §3
said "LÖSCHEN + Logik migrieren", but only the deletion happened.
Result: Tab key did nothing in v1.7.1, and even manually typed
<at:group,key> tokens were never resolved into real auto-translate
payloads on send.

Root cause confirmed empirically via VN-1 diagnostic build
(_logger.LogDebug in SlashCommandCallback proved CallbackCompletion
fires on Tab once the flag is set). Following the diagnose-zuerst
pattern established by Issue #3 to avoid the source-code-only
hypothesis trap from Issue #2.

Migration follows v1.5.6 ChatLogWindow.DrawAutoComplete + ChatTwo
upstream AutoCompleteHandler patterns, but ported to v1.7.0 stil:

- ImGuiInputTextFlags extended with CallbackCompletion (Tab trigger)
  and CallbackAlways (cursor restore via _activatePos analog v1.5.6
  ActivatePos)
- SlashCommandCallback now dispatches three branches: CallbackAlways
  (cursor restore), CallbackCompletion (Tab → word-boundary search
  via Encoding.UTF8.GetString on the byte span, char-offset DTO
  construction to avoid the byte-vs-char drift in v1.5.6's raw
  pointer arithmetic), CallbackEdit (existing slash-command help
  detection, now properly scoped)
- 7 new private state fields (_autoCompleteInfo, _autoCompleteOpen,
  _autoCompleteList, _fixCursor, _autoCompleteSelection,
  _autoCompleteShouldScroll, _activatePos)
- DrawAutoCompletePopup renders the picker at the end of Draw():
  IsWindowAppearing seeds _fixCursor + focus, ListClipper-wrapper
  from Util/SearchSelector.cs (IDisposable, automatic Destroy) for
  the result list, Ctrl+0-9 quick-pick, Enter/Escape handling,
  char-splice commit (_pendingMessage = before + replacement + after)
- AutoCompleteCallback handles popup-input-field fix-cursor seeding,
  Up/Down navigation with wrap-around, Tab cycle in the default case
- TrySend now runs AutoTranslate.ReplaceWithPayload(ref bytes) and
  sends via ChatBox.SendMessageUnsafe(byte[]) with a manual 500-byte
  guard, because SendMessage(string) would route through SanitiseText
  which destroys the binary SeString macro bytes that
  ReplaceWithPayload emits
- AutoCompleteInfo DTO added as sealed internal companion type at the
  end of InputBar.cs (15 LOC, exclusively consumed by InputBar);
  ToComplete is a mutable field rather than auto-property so it can
  be passed as ref to ImGui.InputTextWithHint without CS0206

Verified in-game (Flo): Tab on empty input opens picker with full
list, "fire" + Tab filters correctly, Up/Down/Tab navigate, Enter
commits <at:group,key>, send resolves to real auto-translate payload
in chat, Ctrl+0-9 quick-pick works, Escape closes without commit.
dotnet build clean, dotnet csharpier check clean.

Single minor plan-drift: scroll-to-selected uses
ImGui.SetScrollY(selection * lineHeight) instead of
SetScrollFromPosY(clipper.StartPosY) because the local
ListClipper-wrapper does not expose StartPosY — same UX effect.
2026-05-28 17:23:11 +02:00
JonKazama-Hellion 0319636fc5 fix(chat): route inventory item-link addIfNotPresent into InputBar
The AddonChatLog.OnRefresh hook is registered and fires correctly
when the user picks "Link item" from the inventory right-click menu
in-game. The detour extracts addIfNotPresent="<item>" from the
AtkValue array — verified empirically via a temporary _logger.LogDebug
diagnostic build (eventId=31 valueUInt=C addIfNotPresent=<item>).

Pre-fix the extracted value was discarded with `_ = addIfNotPresent;`
and a comment "Chat-window Activated integration is offline until the
new chat layer surfaces an Activated entry point." The Activated entry
point on the new v1.7.0 component layer has existed since that cycle
(InputBar.AppendPending + InputBar.Activate, same pattern as
PayloadHandler.DrawStatusPopup:546-549), but the rewiring was forgotten
when ChatLogWindow.Activated() was removed.

Route addIfNotPresent through InputBar.AppendPending with a
v1.5.6-equivalent !PendingMessage.Contains() guard to prevent
double-insertion on repeated OnRefresh events. Activate = true marks
the input bar for ImGui.SetKeyboardFocusHere on the next draw, so the
user can immediately keep typing after the link is inserted.

Verified in-game: right-click "Link item" on multiple inventory items
inserts <item> into the HellionChat input bar, repeated link insertion
does not produce <item><item>, MainWindow gains keyboard focus.
2026-05-28 16:03:57 +02:00
JonKazama-Hellion b954a19b67 fix(payload-handler): popup-pfad in MessageList-Child-Scope verschieben
Seit dem v1.7.0-Components-Layer-Refactor lebte der PayloadHandler-
Popup-Render in MainWindow.Draw als _messages.DrawHandlerPopups()-
Aufruf nach dem ##hellion-body-Child-Close. ImGui.OpenPopup (in
RightClickPayload, innerhalb ##hellion-main-area-Child) und
ImGui.BeginPopup (in PayloadHandler.DrawPopups, im MainWindow-Root
nach Child-Close) hashed die Popup-ID per g.CurrentWindow->GetID(...)
window-relativ — also unterschiedlich. OpenPopupStack-Eintrag wurde
nie gefunden, popup.Success blieb false, _popup wurde auf null
zurückgesetzt. Alle vier Popup-Switch-Cases waren tot: URL-Rechtsklick,
Player, Item (inkl. EventItem-Subpfad), Status.

Fix nach v1.5.6/ChatTwo-Pattern: _handler?.Draw() ans Ende von
MessageList.Draw() verschieben. MessageList läuft im
##hellion-main-area-Scope und öffnet selbst kein Child, also teilen
OpenPopup und BeginPopup denselben Window-Stack. ID-Hash matched,
Popup rendert.

DrawHandlerPopups-Wrapper aus MessageList und der Aufruf in
MainWindow.Draw entfallen — kein toter Code mehr (grep
DrawHandlerPopups: 0 Treffer).

Hypothese verifiziert gegen imgui.h:845 + imgui.cpp:12282+12528
(beide BeginPopup-Hash und OpenPopup-Hash sind window-relativ),
v1.5.6 ChatLogWindow.cs:1667 (handler.Draw im
##chat2-messages-Child), ChatTwo ChatLog.Window.cs:620 (identisches
Pattern). Reader-Lock auf tab.Messages bleibt während DrawPopups
gehalten — identisch zu v1.5.6-Semantik.

Verifiziert in-game (Flo): Linksklick auf URL öffnet Browser direkt
(v1.5.6-konform), Rechtsklick öffnet wieder das Kontext-Popup. dotnet
build clean, dotnet csharpier check clean.

Plan-Runde 1 dieses Cycles (4-LOC-Reroute LeftClick → RightClickPayload)
wurde verworfen weil empirischer Test zeigte dass auch Rechtsklick
broken war — der Reroute hätte das Symptom nur sichtbarer gemacht
ohne die Root-Cause zu adressieren.
2026-05-28 15:25:05 +02:00
JonKazama-Hellion 29fb4b92eb fix(input-preview): wire Inside-mode + Tooltip-mode render paths
InputPreview was only rendered for PreviewPosition.Top/Bottom (the
DrawConditions IsWindowMode gate). Inside-mode (the default) and
Tooltip-mode had no caller at all because v1.5.6's inline-render path
lived on the deleted ChatLogWindow and was not migrated to the v1.7.0
Components-Layer.

Wire Inside-mode by calling CalculatePreviewHeight + DrawPreview
inline from MainWindow.DrawMainArea between the message-list child
and the input bar, with the message-list height reserved for the
preview block. Wire Tooltip-mode by sampling IsItemHovered() on the
input text widget inside InputBar.DrawInputField (analog to the
existing _isFocused = ImGui.IsItemFocused() idiom on the same line)
and exposing it as WasInputTextHovered; MainWindow opens the tooltip
after _input.Draw when both the hover-flag and PreviewPosition.Tooltip
are active.

Plan-drift acknowledged: the plan stated Plugin.InputPreview is
statically reachable, but the property was declared as an instance
member on Plugin.cs:101. Hoisted to internal static to match the
plan's intention (analog to Plugin.Config); updated the single
external instance-access site in PluginLifecycle.RegisterWindows
to the type-qualified form.

Verified in-game: Inside-mode preview block appears between message
list and input bar on first keystroke; tooltip-mode shows preview on
text-field hover only; Top/Bottom-mode unchanged; empty buffer hides
the preview in all modes. dotnet build clean, dotnet csharpier check
clean.
2026-05-28 13:21:59 +02:00
JonKazama-Hellion 24d3f69041 fix(host): break InputBar/CommandHelpWindow/MainWindow DI cycle
J + J2 closed a singleton cycle:
  InputBar.ctor -> CommandHelpWindow (J2)
  CommandHelpWindow.ctor -> MainWindow (J)
  MainWindow.ctor -> InputBar (pre-existing)

MS.DI does not detect cycles through FactoryCallSite registrations,
so resolution recursed silently on the async plugin-init thread until
the worker died with an uncatchable StackOverflowException. Dalamud's
LoadAsync task never resolved; the plugin UI hung on "Enabling..."
with no exception in the log. First triggered at Plugin.cs:289
(TypingIpc.ctor needs InputBar).

Fix: break the cycle on the laziest edge.
  - CommandHelpWindow.ctor no longer takes MainWindow.
  - New AttachMainWindow setter wired in
    CommandHelpWindowInitHostedService.StartAsync, mirroring the
    existing §6.2 MessageList.AttachPayloadHandler pattern.
  - UpdateContent throws InvalidOperationException if the setter
    never ran, so a future regression fails loudly instead of a
    silent NullRef during input draw.

Also enable UseDefaultServiceProvider(ValidateOnBuild + ValidateScopes)
so future ConstructorCallSite cycles throw at Build time instead of
silently hanging. Catches reflection-based registrations; will not
catch FactoryCallSite cycles like this one (those still need code review).

Verified via 6 enable/disable cycles in-game; plugin loads cleanly,
Hosting starts, FilterAllTabs completes, command help popup renders
for /em and /say (exercises AttachMainWindow), hover counter ticks
(exercises PayloadHandlerInitHostedService AddonLifecycle wiring).
2026-05-28 08:16:27 +02:00
JonKazama-Hellion f6749d206b chore(polish): cycle-end sweep — drop dead fields, dep-cycle, comments
Accumulated polish across the v1.7.1 R-Block reviewer findings. Single
sweep before Phase-3 Smoke-Gate.

Dep-cycle cleanup (Block H + #30):
- CommandHelpWindow drops the dead _inputBar ctor-param + discard that
  was J's speculative prep; this eliminates the InputBar <-> CommandHelpWindow
  ctor cycle at its root
- InputBar replaces Lazy<CommandHelpWindow> wrapper with direct
  CommandHelpWindow ctor-param now that the cycle is broken
- PluginHostFactory InputBar + CommandHelpWindow DI-regs simplified

Dead-field removals:
- MessageList drops _themes + _resolver (no reads after H's render-path
  swap to _chunkRenderer.DrawChunks)
- InputBar drops FocusedPreview (no consumer wiring in the new architecture)
- InputPreview drops SelectedCursorPos (v1.5.6 letter-by-letter renderer
  artifact, no callers in R1)
- InputPreview drops WhitespaceRegex + partial keyword on class (dead
  GeneratedRegex with no callers)

Visibility fixes:
- InputPreview + CommandHelpWindow + DebuggerWindow ctors flip
  public -> internal for consistency with internal sealed class declarations

DI helper extraction:
- PluginHostFactory MakePayloadHandler private static helper DRYs the
  7-arg list shared between PayloadHandler-singleton and Lender<T> factory

ImGui-rendering fix:
- MessageList.DrawCompactRow uses SameLine(0f, 0f) — eliminates visible
  ItemSpacing.X gap between sender-prefix and chunk content

Bug fixes:
- PayloadHandler.LeftClickPayload drops spurious unsafe keyword (no
  pointer ops in the method body; v1.5.6 had no unsafe here)
- PayloadHandler.StringifyMessage Aggregate seeded with string.Empty to
  fix empty-sequence crash for pure-icon messages
- PayloadHandler.MoveTooltip args==null LogWarning template simplified
  (?.GetType().Name was always null after the null-check — misleading)
- InputBar.SlashCommandCallback drops redundant BufTextLen==0 guard
  (BufTextSpan handles empty correctly)

Comment improvements (WHY-not-WHAT):
- ImGuiUtil.cs payload-state cluster comment moved below Buttons array
- PayloadHandler: §6.9 trimmed to 1 line, FindCharacterForPayload
  documented, hq symbol marker restored, MoveTooltip guard documented
  as defensive v1.7.1 addition, NativeItemTooltips branch explained,
  §4.2 theme colour swap explained
- DebuggerWindow class comment mentions PayloadHandler counters section
- InitHostedServices StopAsync explains params-overload semantics
- InputBar AppendPending null policy vs SetPendingMessage documented,
  CommandManager leading-slash assumption noted
- PluginHostFactory block comment explains singleton+Lender split

Build: 0 warnings, 0 errors. csharpier: clean. Version unchanged.
2026-05-27 23:42:28 +02:00
JonKazama-Hellion d1bfddd9b8 feat(main-window): wire Lender + handler.Draw() (A2, MessageList popups)
A2 completes the deferred Lender-cycle from A1 and addresses the
handler.Draw() gap identified in I code-quality-review:

- MainWindow ctor takes Lender<PayloadHandler> as new param (DI-reg
  extended in PluginHostFactory); _handlerLender.ResetCounter() called
  at top of Draw() as primary pool-reset path (InputPreview has the
  secondary defensive fallback for MainWindow-closed edge case)

- MessageList.DrawHandlerPopups() new passthrough method
  (=> _handler?.Draw()) provides the per-frame popup-tick that
  PayloadHandler needs to render the right-click context popup;
  MainWindow.Draw() calls it after the message-list body renders

Without this fix, right-clicking a player/item/status in the chat log
would silently fail to open a popup (handler.Draw() never fired for the
MessageList's _handler). Phase 3 smoke steps 3/4/5 unblocked.

Polish-Sweep + Smoke-Gate are the last cycle-tasks.
2026-05-27 23:29:18 +02:00
JonKazama-Hellion cba6a16f8e feat(input-bar): wire slash-command callback + AllCommands (J2)
J2 closes the trigger-gap discovered in J review (2026-05-27): J
migrated CommandHelpWindow as a window but the v1.5.6 trigger-path
was never ported. J2 restores it:

- InputBar.cs adds ImGuiInputTextFlags.CallbackEdit + character-level
  callback that reads data.BufTextSpan, detects /-prefix, extracts
  command word, and calls _commandHelpWindow.Value.UpdateContent(desc)
- AllCommands.cs (new file, 1:1 port from v1.5.6) populates a static
  Dictionary<string, TextCommand> from Sheets.TextCommandSheet at
  startup; Plugin.CommandManager.Commands is the fallback for
  non-hardcoded commands
- CommandHelpWindow injected into InputBar via Lazy<T> ctor param to
  break the InputBar <-> CommandHelpWindow circular dep; PluginHostFactory
  DI-reg extended with the Lazy wrapper accordingly

Closes the smoke-step-9 gap. Phase-3 windows are now all reachable
end-to-end (R1 InputPreview, R2 CommandHelpWindow, R3 DebuggerWindow).
2026-05-27 23:19:21 +02:00
JonKazama-Hellion c652a1c450 feat(debugger): reactivate PayloadHandler counters (R3)
K reactivates the debugger's PayloadHandler counter readout
(HandleTooltips / HoveredItem / HoverCounter / LastHoverCounter —
populated in E1's PayloadHandler skeleton). PayloadHandler injected
via DI-extended ctor; class flipped to internal sealed to match
PayloadHandler's internal visibility and avoid CS0051. Plugin.cs
property updated public → internal accordingly (same pattern as I/J).

Last Phase-3 window sub-task before A2 (Lender + handler.Draw fix),
J2 (InputBar slash-callback), Polish-Sweep, and Smoke-Gate.
2026-05-27 22:54:33 +02:00
JonKazama-Hellion 830d247eda feat(command-help-window): full R2 migration (ctor-injected + DI-reg)
J resurrects CommandHelpWindow from the v1.7.0 stub state:

- Class header public → internal sealed
- Ctor takes 4 DI deps (ChunkRenderer, MainWindow, InputBar, ILogger)
  via Factory-Lambda DI-reg. NO Lender<PayloadHandler> — command-help
  chunks are read-only command-description text with no click-targets
  (per spec §5-J + F W8 consumer audit).
- Draw() calls _chunkRenderer.DrawChunks(desc chunks, wrap: true,
  handler: null, lineWidth: 0f) — null-handler is intentional.
- Plugin.cs property visibility flipped public → internal to satisfy
  CS0053 (analogous to I's InputPreview fix).

K (R3 DebuggerWindow counters) and A2 (Lender + handler.Draw fix) are
the remaining Phase-3 sub-tasks before Polish-Sweep + Smoke-Gate.
2026-05-27 21:04:42 +02:00
JonKazama-Hellion 8431fbcf80 feat(input-preview): full R1 migration (PreOpenCheck/PreDraw split + Lender)
I resurrects InputPreview as a fully ctor-injected window:

- Class header public → internal sealed (Components-Layer style); Plugin.cs
  property visibility corrected to internal to match
- Ctor takes 5 DI deps (ChunkRenderer, Lender<PayloadHandler>, MainWindow,
  InputBar, ILogger) via Factory-Lambda DI-reg
- Window-hook split: PreOpenCheck() owns the state (Drawing/PreviewMessage/
  HasEvaluation/PreviewHeight/LastLength), PreDraw() owns position/size
  computation. Matches v1.5.6's split — avoids wasted position-math when
  Window isn't drawn (DrawConditions gates on IsDrawable getter).
- Framework.Update subscribe/unsubscribe removed (PreOpenCheck runs per
  draw-frame, same cadence as Framework.Update for our needs)
- Draw() borrows fresh PayloadHandler per-frame from Lender for popup
  isolation (preview hover doesn't bleed into log)
- Defensive ResetCounter fallback when MainWindow closed + InputPreview
  open — primary path is A2's MainWindow.Draw() ResetCounter

R2/R3 (J/K) next. A2 closes out the Lender DI-cycle for MainWindow.
2026-05-27 20:35:25 +02:00
JonKazama-Hellion 931a152d00 feat(infra): wire PayloadHandlerInitHostedService (AddonLifecycle + setter)
G connects PayloadHandler to the runtime — this is the activation point
after E1-E6 built the type and F registered it in DI:

- StartAsync calls MessageList.AttachPayloadHandler(_payloadHandler) to
  complete the §6.2 cycle-resolution (ctor-cycle was broken by setter,
  this is where the setter actually fires)
- StartAsync registers AddonLifecycle listener for MoveTooltip on
  PostUpdate of "ItemDetail" and "ActionDetail" addons
- StopAsync unregisters the listener
- Both Register/Unregister wrapped in Plugin.Framework.RunOnFrameworkThread
  as defensive insurance — IAddonLifecycle thread-affinity is not
  explicitly documented in Dalamud API; wrap keeps the v1.5.6 runtime
  contract intact (per spec §5-G note)

Mirrors existing IpcManagerInitHostedService / TypingIpcInitHostedService
pattern in Infrastructure/Hosting/. PluginHostFactory adds the
AddHostedService<PayloadHandlerInitHostedService>() registration.

After G, the chunked-message-render pipeline is end-to-end functional:
MessageList renders via ChunkRenderer, _handler is wired so popups fire
on click/hover, MoveTooltip repositions native item-tooltips away from
the chat window.
2026-05-27 20:03:52 +02:00
JonKazama-Hellion 4fb5ee6128 feat(message-list): wire ChunkRenderer ctor + AttachPayloadHandler setter
H integrates the chunk-render pipeline into MessageList:

- Extends ctor to 4 params (themes, resolver, fonts, chunkRenderer);
  TokenResolver preserved as load-bearing dep
- Adds private PayloadHandler? _handler field + internal
  AttachPayloadHandler(PayloadHandler) setter
- Switches DrawCompactRow/DrawCardRow render-path to
  _chunkRenderer.DrawChunks(message.Content, wrap, handler, 0f)
  instead of plain TextUnformatted

Setter-injection for PayloadHandler is the §6.2 cycle-resolution
(PayloadHandler → MainWindow → MessageList → PayloadHandler ctor-cycle
broken by post-construction wiring). G's HostedService.StartAsync will
call AttachPayloadHandler after both singletons resolve.

Also extends MessageList DI-reg in PluginHostFactory.cs with the
ChunkRenderer arg (4th GetRequiredService).
2026-05-27 19:24:20 +02:00
JonKazama-Hellion 2e143686af feat(host-factory): register ChunkRenderer + PayloadHandler + Lender (F)
F adds the 3 new DI registrations needed for the v1.7.1 R-Block:

- ChunkRenderer (4-param ctor: themes, fonts, logger, gameFunctions)
- PayloadHandler singleton (7-param ctor: themes, ipc, functions,
  inputBar, mainWindow, chunkRenderer, logger)
- Lender<PayloadHandler> factory (closure over sp, constructs a fresh
  PayloadHandler per Borrow() — used by InputPreview in Sub-Task I)

All three use Factory-Lambdas because Lender<T> has an internal ctor and
ChunkRenderer/PayloadHandler are internal sealed (ActivatorUtilities
can't reflect into internal ctors per [[reference_hellion_chat_di_container_v150]]).

MainWindow DI-reg update is deferred to Sub-Task A2 (split per Flo
2026-05-27 to avoid the DI-cycle that would otherwise emerge from the
PayloadHandler → MainWindow → MessageList → PayloadHandler graph —
cycle resolved via setter-injection on MessageList in G/H).

G is next: wires PayloadHandlerInitHostedService.StartAsync to register
the AddonLifecycle listener for MoveTooltip and call MessageList.
AttachPayloadHandler. H adds the MessageList ChunkRenderer ctor-param +
AttachPayloadHandler setter.
2026-05-27 18:44:46 +02:00
JonKazama-Hellion d6012a9459 feat(payload-handler): wire MoveTooltip (E6 completes PayloadHandler)
E6 closes out the PayloadHandler resurrection. MoveTooltip handles the
cross-viewport AddonLifecycle tooltip-repositioning logic — reads
MainWindow.LastViewport/LastWindowPos/LastWindowSize (from A1) to filter
events and reposition the native item tooltip away from the chat window.

Whole method marked `public unsafe void` per spec §4.2 (matches v1.5.6
exactly — avoids per-read unsafe-block scoping).

LogWarning added on the unexpected-AddonArgs early-out branch (wires
_logger into real use, prevents CS0414 unused-field warning).

PayloadHandler is now feature-complete. F registers it in DI; G wires
the AddonLifecycle.RegisterListener for MoveTooltip from a HostedService;
H adds MessageList.AttachPayloadHandler setter-injection.
2026-05-27 14:31:23 +02:00
JonKazama-Hellion 121c96f79e feat(payload-handler): wire Hover/Click + LeftClick/RightClick/LinkClick paths
E5 fills the hover/click handler layer (10 methods):

- Hover/Click: replaces E1's empty stubs with real 1:1 bodies; Click uses
  unsafe for FFXIVClientStructs pointer access (UIGlobals.PlaySoundEffect
  via PopupSfx const from E2)
- DoHover: §4.2 swap LogWindow.DefaultText → _themes.Active.Colors.TextPrimary
- HoverStatus, HoverItem, HoverEventItem: 2x _chunkRenderer.DrawChunks
  swaps each (name + description rendering)
- HoverUri: pure 1:1, no LogWindow deps
- LeftClickPayload: unsafe-preserved, Plugin.GameGui static stays
- ClickLinkPayload: pure 1:1, Plugin.ChatGui / Plugin.Framework statics stay
- RightClickPayload: sets _popup field (per E1/E2 field-syntax convention)

Adds FFXIVClientStructs.FFXIV.Client.UI using for UIGlobals; adds
Action alias and DalamudPartyFinderPayload/ChatTwoPartyFinderPayload
aliases required by LeftClickPayload switch arms.

E6 will wire MoveTooltip. After E5, PayloadHandler is functionally complete
except for the MoveTooltip AddonLifecycle wiring.
2026-05-27 13:51:18 +02:00
JonKazama-Hellion 6da8ac93fe feat(payload-handler): wire DrawItem/EventItem/Status/Uri popups + InlineIcon
E4 fills the remaining popup-body methods:

- DrawItemPopup: shows item-name, icon (via InlineIcon), and description
  via _chunkRenderer.DrawChunks; dispatches to DrawEventItemPopup when
  payload.Kind == ItemKind.EventItem (per v1.5.6 internal split)
- DrawEventItemPopup: same shape, Sheets.EventItemSheet/EventItemHelpSheet
  reads, _chunkRenderer.DrawChunks for description rendering
- DrawStatusPopup: status-name + description via _chunkRenderer.DrawChunks;
  "Link" action appends " <status>" via _inputBar.AppendPending (per §4.2)
- DrawUriPopup: open-in-browser + copy-link selectables (no LogWindow deps)
- InlineIcon: pure static helper for popup-icon rendering

Replaces E2's TODO(E4) markers in DrawPopups' Item/Status/Uri switch-cases
with real calls + drawn=true. E5 will wire Hover/Click bodies; E6
MoveTooltip.
2026-05-27 13:20:59 +02:00
JonKazama-Hellion abc0617d58 feat(payload-handler): wire DrawPlayerPopup + FindCharacterForPayload (E3)
E3 fills the player-payload right-click menu. DrawPlayerPopup migrates
1:1 from v1.5.6 with all §4.2/§6.9 substitutions:

- Tell-prefix builds via _inputBar.SetPendingMessage (single string build)
  + _inputBar.Activate = true (replaces v1.5.6's 3x LogWindow.Chat
  incremental writes + LogWindow.Activate flip)
- Channel-switch routes through _mainWindow.ActiveTab?.CurrentChannel?
  .SetChannel(channel) (per §6.3, ActiveTab is public getter on
  MainWindow per v1.7.0 refactor)
- SendFriendRequest / AddToBlacklist / AddToMuteList / AddToTermsList
  / SetEurekaTellChannel all route through injected _functions
- Player-name renderings route through _chunkRenderer.DrawChunks

FindCharacterForPayload migrates 1:1 (pure helper, Plugin.ObjectTable
static stays as-is).

Replaces E2's TODO(E3) marker in DrawPopups' PlayerPayload case with
real DrawPlayerPopup(chunk, player) call.

E4 will wire Item/EventItem/Status/Uri popup bodies; E5 the Hover/Click
bodies; E6 MoveTooltip.
2026-05-27 12:50:23 +02:00
JonKazama-Hellion 63f5a28834 feat(payload-handler): wire DrawPopups + Integrations/ContextFooter/StringifyMessage
E2 fills the popup-dispatch layer of PayloadHandler:
- DrawPopups: switch-dispatch over payload types, with TODO(E3)/(E4)
  markers at the deferred Draw{Player,Item,Status,Uri}Popup call sites
- Integrations: invokes registered IPC integrations (LogWindow.Plugin.Ipc
  -> _ipc substitution per §4.2)
- ContextFooter: ScreenshotMode + HideChat checkboxes (Plugin.Config
  static-bridge substitutions per §4.2)
- StringifyMessage: pure helper, 1:1 from v1.5.6

Adds PopupSfx const (E1 polish — needed by E5's Click for
UIGlobals.PlaySoundEffect). Removes #pragma CS0169 for _popup since
DrawPopups now writes the field; the warning no longer triggers.

E3 will fill DrawPlayerPopup + FindCharacterForPayload; E4 the
Item/Status/Uri popups; E5 the Hover/Click bodies; E6 MoveTooltip.
2026-05-27 12:19:50 +02:00
JonKazama-Hellion e46b6a7520 feat(imgui-util): resurrect WrapText pipeline (~220 LOC from v1.5.6)
Replaces C2's no-op WrapText stub with the full word-wrap pipeline
(WrapText / WrapEncodedLine / CalcWordWrap / DrawText / FindFirstSpace).
ChunkRenderer.DrawChunk's text-path now renders properly wrapped text
with payload hover-highlights and click-binding via PostPayload (which
was already full-ported in C2).

Also adds LastLink and PayloadBounds static fields that C2's PostPayload
port required but did not declare; DrawText needs both for per-segment
hover-rectangle accumulation across wrapped lines.

Unblocks E5's Hover paths that depend on functional WrapText for
status/item tooltip rendering. No structural changes — pure body
migration of the v1.5.6 unsafe word-wrap implementation.
2026-05-27 10:27:58 +02:00
JonKazama-Hellion 2067a54467 feat(payload-handler): add skeleton with 7-param ctor + Draw() popup tick
Replaces the 15-LOC C2 forward-stub with the full PayloadHandler
skeleton. Class header flips to `internal sealed` per §4.1; ctor takes
7 DI-registered services (ThemeRegistry, IpcManager, GameFunctions,
InputBar, MainWindow, ChunkRenderer, ILogger) per Flo decision
2026-05-27 (ChunkRenderer was added to the ctor list to satisfy the
§4.2 _chunkRenderer.DrawChunks references in HoverStatus/HoverItem/
DrawItemPopup paths — those land in E2-E5).

Draw() per-frame popup tick is a 1:1 port from v1.5.6 PayloadHandler.
DrawPopups() call is stubbed as TODO(E2) since that method lands in E2.
Hover/Click signatures remain empty (E5 fills the bodies, but the
signatures must compile so ChunkRenderer + ImGuiUtil callers stay live).

Skeleton-only — DrawPopups/Integrations (E2), DrawPlayerPopup (E3),
DrawItemPopup/DrawStatusPopup (E4), Hover/Click bodies (E5),
MoveTooltip (E6) all defer to their respective sub-sub-tasks.
2026-05-27 09:58:22 +02:00
JonKazama-Hellion 61a1e6bf87 feat(chunk-renderer): wire DrawIcon + icon-dispatch + EmoteCache path
Completes the ChunkRenderer pipeline. DrawIcon is a 1:1 port of v1.5.6
ChatLogWindow.DrawIcon (GFD-icon font-relative rendering via
Plugin.TextureProvider + ImGuiUtil.PostPayload). C2's TODO(C3) stub in
DrawChunk's IconChunk branch is replaced with the real dispatch.
EmotePayload special-case wired via EmoteCache.GetEmote (static helper
per §6.8).

Also adds a one-line rationale comment for the surviving _logger discard
(C2 code-quality-review polish — discard kept because _logger is not yet
consumed; E-task wiring will likely add call-sites later).
2026-05-27 09:29:35 +02:00
JonKazama-Hellion dec0daf30c feat(chunk-renderer): add DrawChunks + DrawChunk text-path (C3 stubs icon)
Resurrects v1.5.6 ChatLogWindow's DrawChunks/DrawChunk text-rendering
pipeline into the new ChunkRenderer Components-Layer class. Text-chunk
path is the full v1.5.6 migration (Plugin.Config.ScreenshotMode,
_themes.Active.Colors.TextPrimary, _fonts.ItalicFont/_fonts.AxisItalic
substitutions applied per §4.2/§4.5); icon-chunk dispatch in DrawChunk
is stubbed pending C3 (EmoteCache + DrawIcon path).

ImGuiUtil.WrapText is forward-stubbed in Util/ImGuiUtil.cs as a no-op
TextUnformatted wrapper — Sub-Task D will replace the body with the
full ~220-LOC word-wrap pipeline. ImGuiUtil.PostPayload is also
forward-stubbed (payload hover/click routing belongs to Sub-Task E).
Both stubs are the cleanest cut to keep DrawChunk's body faithful to
v1.5.6 and avoid temporary fallback paths inside ChunkRenderer.

PayloadHandler.cs is a minimal forward-stub class (Hover + Click stubs
only) required by the DrawChunks/DrawChunk and PostPayload signatures.
Sub-Task E will replace this stub with the full implementation.

Discard pattern from C1 removed for _themes/_fonts (now genuinely
consumed by DrawChunks/DrawChunk); _logger discard kept — not yet
consumed in C2, deferred to E-task wiring.
2026-05-27 08:59:23 +02:00
JonKazama-Hellion 7e541ac842 feat(chunk-renderer): add skeleton + per-ctor salt + player-hide helpers
Extracts v1.5.6's `ChatLogWindow.HidePlayerInString` / `HashPlayer` into
a standalone `Ui/Components/ChunkRenderer` class. C1 lands the skeleton
(ctor + DI-deps + salt + two pure helpers); C2 will add DrawChunks/DrawChunk
text-path; C3 will add DrawIcon + EmoteCache integration.

Salt is per-ctor random matching v1.5.6 session-random behavior — hashed
player names change every plugin reload to avoid stable cross-session
linkage (Spec §6.5 decision).

GameFunctions injected via ctor (not static Plugin.Functions) because
Plugin.Functions is a non-static internal property — injection is the
correct Components-layer pattern for this dependency.

Not yet DI-registered (Sub-Task F) and not yet consumed by MessageList
(Sub-Task H) — class compiles standalone.
2026-05-27 08:19:08 +02:00
JonKazama-Hellion 94fdef38ad feat(main-window): track per-frame window pos/size/viewport for PayloadHandler
Replaces the v1.5.6 `LogWindow.LastViewport/LastWindowPos/LastWindowSize`
window-instance state with public/internal MainWindow surfaces refreshed
at the top of Draw() each frame. PayloadHandler.MoveTooltip in Phase 2
will read these to filter cross-viewport AddonLifecycle events and to
reposition the native item tooltip away from the chat window.

LastViewport is `internal unsafe` (not public) — the only consumer is
PayloadHandler.MoveTooltip in the same assembly; keeping the raw pointer
out of the public surface is the safer default.

Split from Sub-Task A — Lender injection lives in A2 (after F's DI-reg).
2026-05-27 08:08:29 +02:00
JonKazama-Hellion 01fc69efda feat(input-bar): add SetPendingMessage/AppendPending mutators + Activate/FocusedPreview flags
Replaces v1.5.6's direct LogWindow.Chat mutation pattern with typed mutators
that LogWarning + clip/drop on BufferCapacity overflow (silent-overwrite
semantics preserved, but overflow is now observable via /xllog).

Plumbing for v1.7.1 PayloadHandler resurrection — DrawPlayerPopup (tell-
prefix) and DrawStatusPopup (status-link append) will call these mutators
instead of mutating a public field.
2026-05-27 07:59:39 +02:00
JonKazama-Hellion f5f9a4e4da feat(config): bump schema v20→v21 with ScreenshotMode field
Adds persisted ScreenshotMode flag to Configuration (was previously a
ChatLogWindow-instance field in v1.5.6). Schema bump is additive — no
breaking change. SelfTest renamed V20→V21 with matching version-gate
flip and new touch-test for the new field.

Pre-flight for v1.7.1 PayloadHandler-Pipeline Resurrection.
2026-05-27 07:47:15 +02:00
JonKazama-Hellion ced22d73b2 chore(format): csharpier line-break LINQ chain in ThemePickerCategoryStep 2026-05-26 23:02:47 +02:00
JonKazama-Hellion d2b2ebf17f test(selftests): verify TypingIpc state matches input bar 2026-05-26 23:01:59 +02:00
JonKazama-Hellion 125a41c6a0 test(selftests): verify OpenMainUi targets MainWindow not Settings 2026-05-26 23:01:26 +02:00
JonKazama-Hellion dc8d2ae8b7 test(selftests): cover Settings window toggle 2026-05-26 23:00:59 +02:00
JonKazama-Hellion 22bf1dd110 test(selftests): cover theme picker category map 2026-05-26 22:57:11 +02:00
JonKazama-Hellion 4595de5efc test(selftests): implement ColorEditorBufferStep against editing buffer 2026-05-26 22:50:13 +02:00
JonKazama-Hellion 730e15d108 chore: remove v1.7.0 'lands in' placeholders 2026-05-26 20:44:41 +02:00
JonKazama-Hellion 545ddfbfcc chore(ui): delete settings stub from v1.6.0 2026-05-26 20:37:58 +02:00
JonKazama-Hellion f510d01f46 feat(plugin): switch SettingsWindow type to new Ui.Windows namespace 2026-05-26 20:29:35 +02:00
JonKazama-Hellion 490da3e908 feat(settings): add About tab with brand, links, credits 2026-05-26 20:20:53 +02:00
JonKazama-Hellion 262fb3022a feat(settings): add Data & Privacy tab with retention and filter 2026-05-26 20:05:52 +02:00
JonKazama-Hellion 0512d4c9d2 feat(settings): add Channels tab with auto-tell and sidebar configs 2026-05-26 19:53:57 +02:00
JonKazama-Hellion 1f9afe182a feat(settings): add Window tab with layout/opacity/resize 2026-05-26 19:26:32 +02:00
JonKazama-Hellion 2c23a88e9d chore(format): csharpier line-break GeneralTab toggle calls 2026-05-26 19:12:02 +02:00
JonKazama-Hellion 2507ed5197 feat(settings): add Chat tab including command help side 2026-05-26 19:12:01 +02:00
JonKazama-Hellion 7e933cb8ba feat(settings): add General tab with direct-save toggles 2026-05-26 18:57:34 +02:00
JonKazama-Hellion 26c395419a feat(settings): wire Appearance tab with import/export row 2026-05-26 18:51:24 +02:00
JonKazama-Hellion 12bf83b826 feat(windows): add SettingsWindow skeleton (W1) 2026-05-26 18:35:30 +02:00
JonKazama-Hellion 6bbdc67089 feat(settings): register LivePreviewPanel in DI 2026-05-26 18:24:29 +02:00
JonKazama-Hellion 13ca241ac7 feat(settings): render six mock elements in live preview 2026-05-26 18:20:57 +02:00
JonKazama-Hellion 304e1aab20 feat(settings): add LivePreviewPanel skeleton 2026-05-26 18:00:53 +02:00
JonKazama-Hellion cce56610fc feat(settings): register ColorPicker in DI 2026-05-26 17:37:47 +02:00
JonKazama-Hellion eed919e961 feat(settings): wire ColorPicker sections for all 21 slots 2026-05-26 17:33:11 +02:00
JonKazama-Hellion 21689655da feat(settings): add ColorPicker skeleton with lifecycle 2026-05-26 17:05:40 +02:00
JonKazama-Hellion c6f7266194 feat(settings): add ThemePicker with five categories and switch lock 2026-05-26 16:36:54 +02:00
JonKazama-Hellion a73cad1534 feat(settings): add ContentArea wrapper 2026-05-26 16:08:27 +02:00
JonKazama-Hellion bb37e19176 feat(settings): add TabSidebar with seven entries 2026-05-26 15:59:01 +02:00
JonKazama-Hellion ffef5634ed feat(util): add RgbaToVector4 and Vector4ToRgba helpers for color picker 2026-05-26 15:25:31 +02:00
JonKazama-Hellion 947c4b2061 fix(themes): bump example-theme.json to schemaVersion 2 2026-05-26 14:47:02 +02:00
JonKazama-Hellion d156ff4c56 fix(plugin): route OpenMainUi to MainWindow instead of Settings 2026-05-26 14:11:34 +02:00
JonKazama-Hellion 7979568165 refactor(ipc): drop this.-qualifier and trim BuildState comments
Same shadowing-via-instance-property as Plugin.CurrentTab above. Comments
trimmed to default 1-3 line density; security/threading WHY-blocks earn
their lines when they document non-obvious invariants, not standard C#
name resolution.
2026-05-26 14:04:46 +02:00
JonKazama-Hellion 93bfd408bc feat(ipc): wire TypingIpc state from InputBar API 2026-05-26 13:38:21 +02:00
JonKazama-Hellion e01de0403a feat(input): expose state API, wire settings cog, add test hooks 2026-05-26 13:31:00 +02:00
JonKazama-Hellion 11eb7b9e90 fix(themes): tighten editing-buffer save path (tmp cleanup, log-PII, line-refs)
Three review-pass fixes on SaveEditingBuffer:

- Wrap File.Move in try/catch that deletes the .tmp sibling on failure
  (AV-scanner lock, EXDEV, share-violation) then rethrows so the outer
  IOException catch still owns the error path. Avoids accumulating
  '<slug>.json.tmp' litter in the themes dir on retry storms.

- Reduce PII in the five new LogWarning calls that previously included
  full paths containing the user's home directory. Filename-only via
  Path.GetFileName is sufficient for triage; the two forensics-critical
  path-escape log calls keep full paths because diagnosing the escape
  needs the resolved target. WHY-comment anchors the v1.8.0 PII
  re-audit roadmap.

- Replace seven hardcoded 'ThemeRegistry.cs:<line>' references in
  comments with method-name + symbol descriptions so future Switch/
  RefreshCustomCache refactors do not bit-rot the comments.

Build 0/0, csharpier clean.
2026-05-26 13:16:57 +02:00
JonKazama-Hellion 4f81cd1f24 feat(themes): add editing buffer with begin/update/save/discard 2026-05-26 13:03:30 +02:00
JonKazama-Hellion 8e7149cadc fix(ui): guard sidebar row at min drag and widen system-icon match
DrawRow asserted on a zero-width InvisibleButton when the window was
dragged below the pop-out hit threshold — the row now drops out cleanly
under 2px of remaining sidebar width, and the pop-out button only
splits off when there's room for both hit areas. The trailing pop-out
icon is hidden too when its strip is collapsed, so the row stays as a
single selectable strip on extreme drags.

System icon path: ResolveTabIcon used to look only at the first key in
SelectedChannels, so a System tab whose first filter happened to be a
generic ChatType slipped through to Comment. The resolve now walks
every key and keeps the first non-Comment match, and a final
case-insensitive name match flips the icon to fa-cog when the user's
filter set falls completely outside the channel-type table.
2026-05-23 21:08:22 +02:00
JonKazama-Hellion 2f099fd4e1 fix(ui): clickable channel pill, auto-seed channel, kill outer scrollbar
Three smoke bugs from the second in-game test:

1. The channel pill was draw-list only, so it didn't react to clicks
   and there was no way to switch channels inside a tab. The pill now
   has a hit area on top and opens a popup that lists every ChatType
   in tab.SelectedChannels with a ToInputChannel mapping; selecting
   one writes through CurrentChannel.SetChannel.

2. Switching to Allgemein / Gruppe / Linkshell still showed "—"
   because tab.CurrentChannel.Channel stayed at Invalid until somebody
   set it. The sidebar now seeds CurrentChannel on tab activation by
   walking SelectedChannels for the first key with a valid mapping,
   so every tab opens with its own real channel instead of inheriting
   the FC default.

3. MainWindow still surfaced an outer scrollbar next to the message
   list's own scroll. Adding NoScrollbar + NoScrollWithMouse to the
   window flags strips the second bar — the body child owns scroll on
   its own.

Plus the system-icon path: System / BattleSystem / GatheringSystem /
Error / Notice / LootNotice all map to fa-cog now, so the System tab
renders the gear instead of falling back to the generic comment.
2026-05-23 20:58:50 +02:00
JonKazama-Hellion 52b0fa7c67 fix(ui): wire chat send and fix sidebar icons, channel pill, scrollbar
Five smoke bugs from the first in-game test:

1. Sidebar showed fa-comment for every tab because the resolve path
   only honoured tab.Icon. Channel-type fallback restored — auto-tell
   tabs render the envelope, the rest map their first SelectedChannels
   key onto FontAwesome (Linkshells → link, FC → users, Party →
   user-friends, System/Echo → cog, emotes → comments).

2. InputBar's channel pill read from tab.Channel (the saved default),
   which is null on most non-FC tabs and rendered as "—". The pill now
   reads tab.CurrentChannel.Channel first so the runtime input state
   surfaces on every tab, with the saved default as a second fallback.

3. MessageList was making its own ImRaii.Child inside the main-area
   child MainWindow already owns. That nested scroll created the second
   scrollbar on the outer window. The component now lays out directly
   into the parent's scroll region.

4. The input field reserved 90px for the three FontAwesome buttons,
   which clipped them on standard frame padding. Reserve raised to
   130px so the trailing buttons fully render.

5. Pressing Enter dropped the buffer — there was no send wiring. The
   field now uses ImGuiInputTextFlags.EnterReturnsTrue and routes the
   pending message through GameFunctions.ChatBox.SendMessage. Lines
   that don't start with a slash get the active channel's prefix
   prepended so typing in /fc lands on the FC channel instead of the
   current game-side default.

InputBar gains an ILogger<InputBar> for the send-failure path; the
DI registration in PluginHostFactory is updated to match.
2026-05-23 20:50:54 +02:00
JonKazama-Hellion 0109bfd222 test(selftests): add v1.6.0 SelfTest steps from sub-spec
Six new ISelfTestStep entries register with the Dalamud SelfTestRegistry:
SidebarModeAutoSwitch probes the width threshold both above and below the
exact boundary so the >= contract stays pinned; ColorEditorBuffer is a
placeholder until the picker arrives; ConfigMigrationV20 asserts the
schema stamp and the five v20 field defaults; HoverSheenAlloc drives 100
hovered frames against three constant keys and a final un-hover sweep to
exercise the cleanup branch; HonorificHeaderRender runs one Draw call on
the live component to catch IPC fallback crashes; PerformanceBaseline
prints a JSON line of the IO counters so the cycle notes can pick up a
snapshot. MainWindow gets internal accessors so the probes can reach the
sidebar and honorific header without widening the public surface.
2026-05-23 20:35:01 +02:00
JonKazama-Hellion cf4705e01f refactor(ui): retire ChatLogWindow and the v1.5.6 chat-window layer
The legacy ChatLogWindow.cs and its tightly coupled neighbours are gone:
PayloadHandler, Popout, ChatInputBar, AutoCompleteInfo, AutoTellTabTint,
the three tab-icon helpers, the old Ui/StatusBar and Ui/SymbolPicker
behind the components-layer replacements, HellionStyle + helpers, the
CompactInputSubmitter test mirror and the QuickPickerSelfTestStep. The
new component layer (MainWindow + the five components + GlobalStyleScope)
now drives the whole chat surface.

InputPreview, CommandHelpWindow and Debugger lose their ChatLogWindow
backref. The first two are skeleton windows for now — DrawConditions
always returns false until the new chat layer exposes equivalent state.
Debugger keeps the current-tab and vanilla-chat blocks; the payload
counters are explicitly marked offline. DbViewer renders Sender/Content
columns as plain TextValue strings instead of the removed DrawChunks.

GameFunctions.Chat and GameFunctions.KeybindManager keep the hook
plumbing intact but mark every ChatLogWindow.Activated /
ChangeTabDelta / TellSpecial site as offline so the FFXIV-side
integration still compiles and runs without an Activated entry point.
TypingIpc.BuildState reports the IPC state as not-typing / not-focused
until the new chat layer surfaces real focus and buffer state again.

Plugin.cs Draw uses StyleEngine.GlobalStyleScope.Push for the per-frame
theme push and stops calling BeginFrame / FinalizeFrame / HideStateCheck
/ DefaultText through the dead window. ImGuiUtil drops PostPayload +
WrapText + the surrounding word-wrap pipeline. PluginHostFactory and
PluginLifecycle drop the legacy DI singletons and AddWindow entries.

Build is clean and csharpier is clean across the trimmed 131-file tree.
2026-05-23 20:31:12 +02:00
JonKazama-Hellion c9e746a8e3 refactor(settings): reduce SettingsWindow to a stub and drop the tab system
The seven settings tabs and the overview helper are removed. The new
settings UI lands in a later cycle and will be rebuilt from scratch on
the v2.x component layer; keeping the v1.5.6 tab classes around in the
meantime would only carry dead dependencies through the rest of this
cycle. The window stays registered so /hellion settings, the slash
command path, and the UiBuilder open handlers all still resolve.
2026-05-23 20:12:16 +02:00
JonKazama-Hellion ec02a5f381 feat(commands): consolidate /hellion and /clearhellion in Plugin.SetupCommands
/hellion routes through one handler with three subcommands: empty arg
toggles the main window, "settings" toggles the settings stub (full
settings UI lands later), "reset" calls ThemeRegistry.SwitchSilent on the
default slug so a broken custom theme can be unloaded without a settings
UI. /clearhellion now lives next to /hellion instead of inside the chat
window. ChatLogWindow loses its old register/unregister pair so the two
slash-commands stop double-binding.
2026-05-23 20:08:09 +02:00
JonKazama-Hellion 576cd6dafd feat(ui): assemble MainWindow from the components layer
Top-level chat window composes HonorificHeader, Sidebar, MessageList,
InputBar and StatusBar in the layout from the master spec: header row,
horizontal body (sidebar + main area with messages + input), status
strip pinned to the bottom. Component types are fully qualified through
the Ui.Components prefix so the v1.5.6 Ui.StatusBar type cannot shadow
the new layer through parent-namespace resolution before it is removed.
Toggle is a new-shadow on Window.Toggle so the open path also writes
Config.MainWindowOpen; OnClose covers the close path through the base
behaviour. InputBar.Height is now public so the layout math can reach
it from outside the components folder.
2026-05-23 19:52:37 +02:00
JonKazama-Hellion 0fc2512f3e feat(ui): rebuild StatusBar inside the components layer
Same 1Hz-cached slot layout (channel indicator, privacy badge, counts,
tells, version + brand) but ThemeRegistry and FontManager arrive via
constructor injection rather than the Plugin static bridge, and Draw
takes the active tab directly so the component does not have to reach
back through Plugin.CurrentTab. Pure helpers (FormatCounts, FormatTells,
AggregateForStatusBar) stay static so the build suite can pin them
without an ImGui frame. The v1.5.6 Ui/StatusBar.cs stays in place until
the cleanup block removes it.
2026-05-23 19:35:50 +02:00
JonKazama-Hellion 36afce21e5 feat(ui): add InputBar with channel pill and symbol picker overlay
Channel pill picks Token.AccentEmber when the tab is a tell (matched by
IsTempTab + a set TellTarget) and Token.AccentPrimary otherwise, so the
tinted background reads as the channel type at a glance. SymbolPicker
runs as an overlay popup — the inserted fragment splices straight into
the pending buffer up to a 500-char cap. Send wiring and the settings
button arrive when the main window assembles the components.
2026-05-23 19:17:25 +02:00
JonKazama-Hellion bdfb1298ad feat(ui): migrate SymbolPicker into the components layer
Lifted out of Ui/ into Ui/Components and registered as a DI singleton so
the new InputBar can consume it via constructor injection. PUA tab still
sources from SeIconChar, BMP tab keeps the server-verified whitelist
verbatim. The old Ui/SymbolPicker.cs stays in place until the cleanup
block removes the v1.5.6 file.
2026-05-23 19:12:18 +02:00
JonKazama-Hellion eb95968750 feat(ui): add MessageList with two-mode virtualisation
Compact mode reuses ImGuiListClipper because rows are a constant line
height; card mode falls back to a linear render with a per-message height
cache and an IsItemVisible skip path so off-screen rows place a Dummy of
the cached height instead of running the full render. Bottom-lock detects
whether the user was pinned to the bottom before the layout pass and
re-pins after new rows land. Renders text-only via SeString.TextValue for
this cycle — full chunk and payload rendering re-attaches later, so the
component shape stays correct without dragging the v1.5.6 chunk pipeline
into the new layer.
2026-05-23 18:53:38 +02:00
JonKazama-Hellion 6ab2e9cece feat(ui): add Sidebar component with width auto-switch
Channel-list panel for the chat window's left side. Auto-switches between
icon-only (38px) and expanded (150px) based on
Config.SidebarAutoSwitchThresholdPx. Each row renders a FontAwesome tab
icon, an expanded-mode name label, a hover-sheen sweep keyed on the tab
identifier, and a pop-out affordance — both the trailing hover button and
the right-click context menu route through a log stub until the channel
popout pool comes online. Glyph table is inlined so the Ui layer carries
its own lookup after the standalone mapping file is removed.
2026-05-23 18:30:29 +02:00
JonKazama-Hellion 0e0c563608 feat(ui): add HonorificHeader component
30px header row pinned to the top of the chat window. Crown always renders
as a brand anchor — even with the Honorific IPC down — while the bracketed
title only appears when CurrentTitle has content. First-frame guard reads
FontManager.FontsReady so layout math never runs against placeholder font
metrics.
2026-05-23 18:17:33 +02:00
JonKazama-Hellion 9c490fa066 feat(services): add TellRouterService stub
Skeleton for the upcoming auto-open routing. Subscribes to
ChatGui.ChatMessageUnhandled and Dispose unsubscribes — when the routing
logic lands, it drops into OnChatMessage without touching the DI graph or
Plugin.cs registration.
2026-05-23 18:12:18 +02:00
JonKazama-Hellion 44c14ace2c feat(fonts): add FontsReady gate property
Returns true once every required atlas-owned handle reports Available.
Components will gate their first-frame draw on this so the layout math
runs against the real atlas rather than placeholder metrics. ItalicFont
null counts as ready because that means italics are disabled in config.
2026-05-23 18:10:36 +02:00
JonKazama-Hellion 53ed154103 feat(config): bump schema to v20 with style-refactor visibility fields
Adds MainWindowOpen, SettingsWindowOpen, MaxParallelPopouts (channel popout
pool size), TellAutoOpenMode (Off/Sidebar/TopTab/Popout) and
SidebarAutoSwitchThresholdPx. Migration is additive — field initializers
fill defaults for v19 configs, the Plugin.cs schema gate bumps the version
stamp after load. UpdateFrom gets explicit sync statements for all five so
settings-save edits do not drop them.
2026-05-23 18:08:34 +02:00
JonKazama-Hellion 620dfe9ea0 feat(themes): bump JSON schema to v2 with typography roundtrip
Loader returns Theme? — null is the silent hard-cut skip for v1 files so
the v2.x refactor stays free of legacy-mapping code. v2 adds an optional
typography{} block with overrideGlobalFontSizePt and overrideSymbolsFontSizePt
slots, both nullable. ThemeRegistry.RefreshCustomCache gets a null guard
so the yield path drops skipped files cleanly. Writer emits typography{}
with explicit nulls so hand-edited files show the available knobs.
2026-05-23 17:38:23 +02:00
JonKazama-Hellion cd9e43c183 feat(style-engine): add DrawListExtensions primitives
Custom-drawing primitives consumed by upcoming components: DrawHoverSheen
with sweep tracking via a static dictionary scoped to constant element-id
keys, DrawGlowBorder using squared-fade layer rects, DrawSlipPolygon as
unsafe stackalloc six-point chamfered polygon, and DrawHonorificHeader for
the crown plus bracketed title. BuildSlipPolygon is internal so the build
suite can pin the geometry without spinning up an ImGui frame.
2026-05-23 17:04:33 +02:00
JonKazama-Hellion b8299a90ca feat(style-engine): add PushStack as ImRaii bridge
DI-singleton that pairs Token lookups with ImRaii's tracked push/pop
machinery. Begin() returns a disposable PushScope with fluent Color, Style
(float/Vector2) and Font methods; reverse-order dispose runs through the
collected IDisposables. Counter-symmetry and exception-safety come from
ImRaii, this layer just handles the token → ImGuiCol resolution and the
RGBA → ABGR conversion at the ImGui boundary.
2026-05-23 16:36:01 +02:00
JonKazama-Hellion d89540de52 feat(style-engine): add TokenResolver and TokenMap
Semantic token layer between code and ThemeColors slots. 41 tokens in three
categories: 24 ImGui-slot tokens with TokenMap mapping to ImGuiCol, 11
custom-drawing tokens that throw on ToImGuiCol, 6 derived surface/text
tokens that lerp from base slots so user picks propagate without inflating
the persisted slot count. Resolver values are RGBA; callers convert at the
ImGui boundary.
2026-05-23 15:59:36 +02:00
279 changed files with 34279 additions and 15883 deletions
+71 -32
View File
@@ -22,9 +22,9 @@ on:
- 'v*'
# Manual recovery trigger. Use Gitea's "Run workflow" UI and select the
# tag (e.g. v1.4.4) from the Ref dropdown - not main. The Validate tag
# ref step below hard-fails if a non-tag ref is selected, because the
# release-action reads GITHUB_REF directly and rejects anything that
# does not start with refs/tags/.
# ref step below hard-fails if a non-tag ref is selected: the release
# name and body are both derived from the tag, so a branch ref would
# publish a release named after a branch.
workflow_dispatch:
permissions:
@@ -37,11 +37,8 @@ jobs:
timeout-minutes: 20
steps:
# release-action@main reads GITHUB_REF directly (its action.yml
# does not declare a tag_name input). Validate up-front so manual
# dispatches from a branch ref fail loud here instead of burning
# a full build before the final step errors out with "ref X is
# not a tag".
# Validate up-front so a manual dispatch from a branch ref fails loud
# here instead of burning a full build before the publish step notices.
- name: Validate tag ref
run: |
if [[ "${GITHUB_REF}" != refs/tags/v* ]]; then
@@ -156,28 +153,70 @@ jobs:
Write-Host $body
Write-Host "----------------------------------------"
# release-action@main only declares files/title/body/pre_release/
# draft/api_key/insecure as inputs (see its action.yml). It silently
# ignores anything else, including body_path and tag_name. The tag
# itself comes from GITHUB_REF, the body must be passed inline via
# body:, so we re-emit release-body.md as a step output first.
- name: Expose release body for release-action
id: body
shell: bash
run: |
{
echo 'content<<RELEASE_BODY_EOF'
cat release-body.md
echo 'RELEASE_BODY_EOF'
} >> "$GITHUB_OUTPUT"
# Gitea-native release action. Creates the release if the tag has no
# release yet, or updates the existing one with latest.zip attached
# and the generated body. The auto-injected GITHUB_TOKEN on Gitea
# Actions has Gitea-API scope and is sufficient for release write.
# The tag comes from GITHUB_REF, the body from the step above. Posted with
# curl rather than gitea.com/actions/release-action, which declares
# `using: go` and has to be compiled by the runner -- act cannot do that
# here and the step dies with exec: "go": executable file not found, exit
# 127, after a build that otherwise succeeded. This runs as a plain shell
# step in the job image, which has curl and python3.
#
# Idempotent on purpose: a re-run against an existing release reuses it and
# replaces the asset instead of failing on the duplicate.
- name: Attach to Gitea release
uses: https://gitea.com/actions/release-action@main
with:
files: ${{ steps.locate.outputs.path }}
body: ${{ steps.body.outputs.content }}
api_key: ${{ secrets.GITHUB_TOKEN }}
shell: bash
env:
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ZIP_PATH: ${{ steps.locate.outputs.path }}
TAG_NAME: ${{ github.ref_name }}
run: |
set -euo pipefail
api="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}"
auth="Authorization: token ${GITEA_TOKEN}"
# Responses land in a file before anything reads them, rather than
# being piped straight into an interpreter. The interpreter is inline
# either way and the server only ever supplies data, but a scanner
# cannot tell those apart from curl-pipe-shell -- and holding the
# response makes it inspectable when a call misbehaves.
get_release_id() {
if curl -sf -H "$auth" "$api/releases/tags/${TAG_NAME}" -o release.json; then
python3 -c 'import json; print(json.load(open("release.json")).get("id",""))'
fi
}
rel_id="$(get_release_id || true)"
if [ -z "$rel_id" ]; then
python3 - <<'PYCREATE' > create.json
import json, os
body = open("release-body.md", encoding="utf-8").read()
print(json.dumps({
"tag_name": os.environ["TAG_NAME"],
"name": os.environ["TAG_NAME"],
"body": body,
"draft": False,
"prerelease": False,
}))
PYCREATE
curl -sf -X POST -H "$auth" -H "Content-Type: application/json" \
-d @create.json "$api/releases" -o created.json
rel_id="$(python3 -c 'import json; print(json.load(open("created.json"))["id"])')"
echo "Created release $rel_id for ${TAG_NAME}"
else
echo "Reusing release $rel_id for ${TAG_NAME}"
fi
# A same-named asset from an earlier attempt has to go, or the upload
# collides with it. This is the state a recovery run finds.
curl -sf -H "$auth" "$api/releases/${rel_id}/assets" -o assets.json
old_id="$(python3 -c 'import json; print(next((a["id"] for a in json.load(open("assets.json")) if a["name"]=="latest.zip"), ""))')"
if [ -n "$old_id" ]; then
curl -sf -X DELETE -H "$auth" "$api/releases/${rel_id}/assets/${old_id}"
echo "Replaced existing latest.zip (asset $old_id)"
fi
curl -sf -X POST -H "$auth" \
-F "attachment=@${ZIP_PATH};filename=latest.zip" \
"$api/releases/${rel_id}/assets?name=latest.zip" -o uploaded.json
python3 -c 'import json; a=json.load(open("uploaded.json")); print("Attached", a["name"], a["size"], "bytes")'
+11
View File
@@ -0,0 +1,11 @@
---
subtitle: "Rebuilt, Repaired, Reset"
versionsnatur: "Major-Release mit Config-Reset"
---
- **Deine Einstellungen werden zurückgesetzt.** Neun Zyklen Umbau haben gespeicherte Werte hinterlassen, die auf Oberflächen zeigen, die es nicht mehr gibt. Neu anzufangen ist der einzige Weg, dass alle dieselben Vorgaben haben. **Dein Nachrichtenverlauf bleibt unberührt**, der liegt in einer eigenen Datenbank. Die alten Einstellungen liegen als `HellionChat.json.pre-2.0.0.bak` daneben.
- **Behoben, und mehrere davon haben Daten verloren oder versteckt:** Die rückwirkende Bereinigung ließ sich nie anwenden. Das Verdichten der Datenbank schlug fehl und meldete danach, es sei nichts gelöscht worden, während alles weg war. Gelöschte Nachrichten blieben im Suchindex. Angepinnte Flüster-Tabs kamen eine ganze Sitzung lang leer hoch. Der Export schrieb ungültiges JSON. Ein Auskoppelfenster mit Titelleiste ließ sich nicht schließen. Ein 403 eines Emote-Dienstes riss alle 65 funktionierenden Emotes mit.
- **Was sich am Speichern ändert:** Das Kanalraster entscheidet jetzt allein. Bisher griff die Unbekannt-Absicherung auch bei bekannten Kanälen, ein abgewählter Kanal wurde also trotzdem geschrieben. Wen das betraf, der speichert ab jetzt weniger. Nichts in der Datenbank wird angefasst.
- **Jedes Fenster zeichnet das Plugin selbst** und alle sprechen eine Sprache: Struktur trägt die Typografie, alles Drückbare bekommt eine Fläche, jede Farbe wird gegen ihren Untergrund gemessen. Dazu benannte Typo-Rollen, Zeitstempel in eigener Spalte, kursive Systemmeldungen.
- **Wieder erreichbar:** Export, Tab-Editor, Datenbankpflege und Anpinnen hatten beim Umbau ihre Zugänge verloren. Der Screenshot-Modus erreichte eine von vier Flächen mit Tab-Namen, jetzt alle vier. Der DSGVO-Hinweis beim Profil "Volle Historie" war in 25 Sprachen übersetzt und seit Mai unsichtbar.
- **Gestrichen:** sechs Einstellungen mit Regler, gespeichertem Wert und ohne jeden Leser. Ein Regex-Filter pro Tab, den der spieleigene Wortfilter abdeckt. Ein Assistenten-Häkchen, das abgefragt, als angewendet gemeldet und nie gelesen wurde.
- **Neu:** Emote-Tab im Standard-Layout (Testerwunsch), Orts- und Serverzeit in der Statusleiste, Screenshot-Modus aus der Eingabezeile erreichbar, `/hellion wizard`, ein Stil-Labor unter `/hellion lab`, und ein Hinweis im Assistenten, dass Plugins in FFXIV eine Grauzone sind und nicht in öffentliche Kanäle gehören.
+7
View File
@@ -0,0 +1,7 @@
---
subtitle: "Hotfix"
versionsnatur: "Hotfix ohne sichtbare Änderungen"
---
- **Nichts Neues zu sehen.** Wer 2.0.0 in der ersten Stunde gezogen hat, sollte trotzdem updaten: das 2.0.0-Archiv wurde ohne eine Abhängigkeits-Aktualisierung gebaut, die hier drin ist.
- **MessagePack von 3.1.4 auf 3.1.7.** Das Paket serialisiert die Nachrichten-Payloads in der lokalen Datenbank. Die Meldungen betreffen die Rekursionstiefe in `Skip` und einen Fehler in der LZ4-Dekomprimierung, beide nur über präparierte Eingaben erreichbar. Das Plugin schreibt und liest ausschließlich seine eigenen Bytes in einer lokalen Datei, praktisch bräuchte ein Angreifer also schon Schreibzugriff darauf. Trotzdem gehoben, weil es nichts kostet.
- **Der Release-Workflow hängt sein Archiv wieder selbst an.** Bei 2.0.0 lief der Build sauber durch und scheiterte dann am Veröffentlichen, weshalb dieses Release von Hand fertiggestellt werden musste.
+7
View File
@@ -0,0 +1,7 @@
---
subtitle: "Emotes raus, Platzhalter gefixt"
versionsnatur: "Aufräum-Release"
---
- **BetterTTV-Emotes sind raus.** Der Endpunkt für geteilte Emotes liegt hinter einer Anmeldung, und von dort kam fast alles. Übrig blieben 54 überwiegend statische Bilder aus der Twitch-Frühzeit, davon genau eines animiert, und das wollte 492 Einzelbilder und 37 MB Grafikspeicher. Das Plugin macht jetzt **gar keine ausgehenden Netzwerkaufrufe** mehr. Gespeicherte Nachrichten mit Emotes bleiben lesbar und zeigen den getippten Code.
- **Fünf Beschreibungen im Fenster-Tab zeigten `{0}` statt des Plugin-Namens.** Betroffen waren alle 25 Sprachen, im Deutschen fiel es zuerst auf, weil der Platzhalter dort am Satzanfang steht. Ein Test prüft das jetzt dauerhaft.
- **Neue Vorschaubilder** im Plugin-Installer. Die alten waren vom 8. Mai und zeigten die Oberfläche vor dem Umbau.
+36
View File
@@ -0,0 +1,36 @@
using Lumina.Excel.Sheets;
namespace HellionChat;
// Ported 1:1 from v1.5.6 ChatLogWindow.SetUpAllCommands. Provides a fast
// lookup from slash-command string to the game's TextCommand row so the
// InputBar callback can feed descriptions to CommandHelpWindow without
// hitting the sheet on every keystroke.
internal static class AllCommands
{
private static readonly Dictionary<string, TextCommand> Commands = BuildCommands();
private static Dictionary<string, TextCommand> BuildCommands()
{
var dict = new Dictionary<string, TextCommand>(StringComparer.Ordinal);
foreach (var command in Sheets.TextCommandSheet)
{
if (!command.Command.IsEmpty)
dict.TryAdd(command.Command.ToString(), command);
if (!command.ShortCommand.IsEmpty)
dict.TryAdd(command.ShortCommand.ToString(), command);
if (!command.Alias.IsEmpty)
dict.TryAdd(command.Alias.ToString(), command);
if (!command.ShortAlias.IsEmpty)
dict.TryAdd(command.ShortAlias.ToString(), command);
}
return dict;
}
public static bool TryGetValue(string command, out TextCommand textCommand) =>
Commands.TryGetValue(command, out textCommand);
}
+205 -80
View File
@@ -21,7 +21,15 @@ internal sealed class AutoTellTabsService : IDisposable
private readonly MessageManager _messageManager;
private readonly MessageStore _store;
private readonly ILogger<AutoTellTabsService> _logger;
private readonly object _tempTabsLock = new();
// Tabs-list structure lock now lives on Plugin (neutral owner) so the
// MessageManager refilter can share it. See Plugin.TabsListLock.
private object TabsListLock => _plugin.TabsListLock;
// Bumped whenever something wipes unpinned temp tabs wholesale (logout).
// HandleTell reads it before releasing the lock and re-checks after, so a
// tab built in between is discarded instead of outliving the wipe.
private int _tabGeneration;
// Hard cap on pinned TempTabs so the sidebar doesn't inflate over years
// of usage. Separate pool from AutoTellTabsLimit (15) — pinned tabs live
@@ -31,6 +39,10 @@ internal sealed class AutoTellTabsService : IDisposable
private bool _initialized;
// Set when Initialize ran before a character was available; cleared once the
// history has actually been loaded.
private bool _rehydratePending;
internal AutoTellTabsService(
Plugin plugin,
MessageManager messageManager,
@@ -46,8 +58,8 @@ internal sealed class AutoTellTabsService : IDisposable
// Derived from the tab list on read. Pin/Unpin/Promote/Logout simply
// mutate IsPinned or remove tabs — the count adapts automatically.
// Replaces the F2.1 Interlocked counter because the new pin-state
// transitions are cold-path and don't need lock-free reads.
// Replaces an Interlocked counter: the pin-state transitions are cold-path
// and don't need lock-free reads.
internal int ActiveTempTabCount =>
Plugin.Config.Tabs.Count(TabLifecycleHelpers.IsInUnpinnedPool);
@@ -68,12 +80,30 @@ internal sealed class AutoTellTabsService : IDisposable
RehydratePinnedTabs();
_messageManager.MessageProcessed += HandleTell;
Plugin.ClientState.Login += OnLogin;
Plugin.ClientState.Logout += OnLogout;
_initialized = true;
}
// Deferred when the plugin starts before a character is logged in, which is
// the normal case: the game loads plugins at boot. CurrentContentId is 0
// until then, so the history query would look up tells for character zero,
// find none, and leave every pinned tab blank for the whole session.
//
// Only visible to someone who actually pins a tell tab AND starts the game
// with the plugin already installed. Reloading the plugin in a running
// session -- what a developer does all day -- hides it completely.
private void RehydratePinnedTabs()
{
if (_messageManager.CurrentContentId == 0)
{
_logger.LogDebug("[Pin] Rehydrate deferred: no character yet, waiting for login");
_rehydratePending = true;
return;
}
_rehydratePending = false;
var pinned = Plugin.Config.Tabs.Count(TabLifecycleHelpers.IsInPinnedPool);
_logger.LogDebug($"[Pin] Rehydrate scan: {pinned} pinned tab(s) found");
@@ -114,6 +144,7 @@ internal sealed class AutoTellTabsService : IDisposable
return;
}
Plugin.ClientState.Login -= OnLogin;
Plugin.ClientState.Logout -= OnLogout;
_messageManager.MessageProcessed -= HandleTell;
_initialized = false;
@@ -147,15 +178,19 @@ internal sealed class AutoTellTabsService : IDisposable
return;
}
lock (_tempTabsLock)
// Three steps, because building the tab pulls history out of the store and
// that must not happen under TabsListLock (the query sorts the whole
// receiver history). Step 1 and 3 are locked, step 2 is not.
int generation;
lock (TabsListLock)
{
var existing = FindTempTab(partner.Value.Name, partner.Value.World);
if (existing != null)
{
// Already routed via MessageManager pipeline. Repair the
// tell-target if the fallback hit a pinned tab whose
// TellTarget didn't survive a previous round-trip — keeps
// FindTempTab fast on the next message.
// Already routed via MessageManager pipeline — no AddMessage here,
// HandleTell runs after the delivery loop. Repair the tell-target if
// the fallback hit a pinned tab whose TellTarget didn't survive a
// previous round-trip — keeps FindTempTab fast on the next message.
if (
existing.IsPinned
&& (existing.TellTarget is null || !existing.TellTarget.IsSet())
@@ -172,12 +207,29 @@ internal sealed class AutoTellTabsService : IDisposable
return;
}
if (ActiveTempTabCount >= Plugin.Config.AutoTellTabsLimit)
generation = _tabGeneration;
}
var tab = BuildTempTabWithHistory(partner.Value, message);
lock (TabsListLock)
{
// A logout in between wiped the unpinned pool; committing now would
// resurrect a tab for a character we already left.
if (generation != _tabGeneration)
return;
// Someone else (self-test, UI) may have created the tab while we built
// ours. Hand the message to theirs and drop what we built — unlike the
// early return above, this tab appeared after the delivery loop ran.
var raced = FindTempTab(partner.Value.Name, partner.Value.World);
if (raced != null)
{
DropOldestTempTab();
raced.AddMessage(message, unread: true);
return;
}
SpawnTempTab(partner.Value, message);
CommitTempTab(tab);
}
}
@@ -218,7 +270,7 @@ internal sealed class AutoTellTabsService : IDisposable
return null;
}
private static Tab? FindTempTab(string name, uint world)
internal static Tab? FindTempTab(string name, uint world)
{
var byTarget = Plugin.Config.Tabs.FirstOrDefault(t =>
t.IsTempTab
@@ -239,45 +291,60 @@ internal sealed class AutoTellTabsService : IDisposable
);
}
// Lock-protected lookup for the framework-thread caller (TellRouterService).
// Config.Tabs is mutated under the shared Plugin.TabsListLock on the worker thread,
// so a framework-tick reader must take the same lock to avoid enumerating the list
// mid-mutation.
internal Tab? FindTempTabSafe(string name, uint world)
{
lock (TabsListLock)
return FindTempTab(name, world);
}
internal void DropOldestTempTab()
{
// Pinned tabs live in their own bucket (MaxPinnedTempTabs) and are
// never drop candidates. They leave the bucket only via Unpin or
// PromoteToPermanent.
var victim = Plugin
.Config.Tabs.Select((tab, idx) => (Tab: tab, Index: idx))
.Where(t => TabLifecycleHelpers.IsInUnpinnedPool(t.Tab))
.OrderByDescending(t => t.Tab.IsGreeted)
.ThenBy(t => t.Tab.LastActivity)
.FirstOrDefault();
if (victim.Tab == null)
// Lock the list-structure ops so the (currently caller-less) Unpin path
// can't race the worker; re-entrant when HandleTell already holds the lock.
lock (TabsListLock)
{
return;
}
// Pinned tabs live in their own bucket (MaxPinnedTempTabs) and are
// never drop candidates. They leave the bucket only via Unpin or
// PromoteToPermanent.
var victim = Plugin
.Config.Tabs.Select((tab, idx) => (Tab: tab, Index: idx))
.Where(t => TabLifecycleHelpers.IsInUnpinnedPool(t.Tab))
.OrderByDescending(t => t.Tab.IsGreeted)
.ThenBy(t => t.Tab.LastActivity)
.FirstOrDefault();
// Clean up pop-out window if tab is popped out
if (victim.Tab.PopOut)
{
var popout = _plugin.ChatLogWindow.ActivePopouts.FirstOrDefault(p =>
p.TabIdentifier == victim.Tab.Identifier
);
if (popout != null)
if (victim.Tab == null)
{
popout.IsOpen = false;
return;
}
}
Plugin.Config.Tabs.RemoveAt(victim.Index);
var dropped = victim.Tab;
// By reference, not by index: the index came from a Select() earlier in
// this block and would point at the wrong tab if anything shifted the list.
Plugin.Config.Tabs.Remove(dropped);
// Re-anchor active tab to avoid silent switch when tab is dropped
if (victim.Index <= _plugin.LastTab)
{
_plugin.WantedTab = 0;
// Re-anchor the UI selection if it pointed at the dropped tab, and close any
// pop-out window the dropped tab owned. Both run on the PendingMessage worker
// thread and touch window state the Draw path reads (OnTabActivated re-seed +
// the pool's Unbind), so marshal onto the framework thread to serialize with
// Draw (reference_dalamud_framework_thread). TryClose is idempotent: a tab that
// was never popped is a silent no-op.
Plugin.Framework.RunOnFrameworkThread(() =>
{
_plugin.ChannelPopoutPool.TryClose(dropped.Identifier);
_plugin.MainWindow?.ResetActiveTabIfRemoved(dropped);
});
}
}
private void SpawnTempTab((string Name, uint World) partner, Message currentMessage)
// Runs WITHOUT TabsListLock: PreloadHistory hits the store, which used to hold
// the lock across a query that sorted the whole receiver history. The tab is not
// public until CommitTempTab adds it, so building it unlocked is safe.
private Tab BuildTempTabWithHistory((string Name, uint World) partner, Message currentMessage)
{
var tab = BuildTempTab(partner.Name, partner.World);
@@ -286,13 +353,40 @@ internal sealed class AutoTellTabsService : IDisposable
tab.AddMessage(currentMessage, unread: true);
// Open as pop-out if configured (set before Tabs.Add for next render-tick)
// Flag the tab as a pop-out if configured; the marshalled TryOpen below reads
// that flag to open the real window.
if (Plugin.Config.AutoTellTabsOpenAsPopout)
{
tab.PopOut = true;
}
return tab;
}
// Caller MUST hold TabsListLock.
private void CommitTempTab(Tab tab)
{
if (ActiveTempTabCount >= Plugin.Config.AutoTellTabsLimit)
{
DropOldestTempTab();
}
Plugin.Config.Tabs.Add(tab);
// Actually open the pop-out window for the flagged tab — without this the
// flag was dead (a PopOut tab with no window). CommitTempTab runs on the
// PendingMessage worker thread under Plugin.TabsListLock; TryOpen does
// OnTabActivated + Bind (window state Draw reads), so marshal onto the
// framework thread. If the pool is full, drop the flag so it never claims a
// window it didn't get (flag/window parity).
if (tab.PopOut)
{
Plugin.Framework.RunOnFrameworkThread(() =>
{
if (!_plugin.ChannelPopoutPool.TryOpen(tab))
tab.PopOut = false;
});
}
}
private static Tab BuildTempTab(string playerName, uint worldRowId)
@@ -300,6 +394,7 @@ internal sealed class AutoTellTabsService : IDisposable
return new Tab
{
Name = FormatTabName(playerName, worldRowId),
NameCameFromPartner = true,
IsTempTab = true,
AllSenderMessages = true,
TellTarget = new TellTarget(playerName, worldRowId, 0, TellReason.Direct),
@@ -407,7 +502,7 @@ internal sealed class AutoTellTabsService : IDisposable
return;
}
lock (_tempTabsLock)
lock (TabsListLock)
{
// Guard against frame-race: sidebar might render a tab already removed by LRU or logout
if (!Plugin.Config.Tabs.Contains(tab))
@@ -419,43 +514,53 @@ internal sealed class AutoTellTabsService : IDisposable
}
}
// Fires on the login that follows a boot-time start, and on every character
// switch after one. Guarded by the pending flag so a switch does not append
// a second copy of the history to tabs that already have it.
private void OnLogin()
{
if (!_rehydratePending)
return;
RehydratePinnedTabs();
}
private void OnLogout(int type, int code)
{
lock (_tempTabsLock)
lock (TabsListLock)
{
// Pinned TempTabs must survive char-switch — that's the whole point
// of pinning. Only unpinned ones get stripped.
var lastIndex = _plugin.LastTab;
var lastIndexValid = lastIndex >= 0 && lastIndex < Plugin.Config.Tabs.Count;
var currentWasUnpinnedTempTab =
lastIndexValid
&& TabLifecycleHelpers.IsInUnpinnedPool(Plugin.Config.Tabs[lastIndex]);
var active = _plugin.MainWindow?.ActiveTab;
var poppedTempTabIds = Plugin
.Config.Tabs.Where(t => TabLifecycleHelpers.IsInUnpinnedPool(t) && t.PopOut)
.Config.Tabs.Where(t =>
TabLifecycleHelpers.IsInUnpinnedPool(t)
&& _plugin.ChannelPopoutPool.IsOpen(t.Identifier)
)
.Select(t => t.Identifier)
.ToList();
if (poppedTempTabIds.Count > 0)
{
var poppedSet = poppedTempTabIds.ToHashSet();
foreach (
var popout in _plugin
.ChatLogWindow.ActivePopouts.Where(p => poppedSet.Contains(p.TabIdentifier))
.ToList()
)
{
popout.IsOpen = false;
}
}
// Close any pop-out window an unpinned temp tab owns before the tabs leave
// the list. Filtering on the live pool (not the PopOut flag) also catches
// manually right-clicked pop-outs, which never set the flag.
foreach (var id in poppedTempTabIds)
_plugin.ChannelPopoutPool.TryClose(id);
Plugin.Config.Tabs.RemoveAll(TabLifecycleHelpers.IsInUnpinnedPool);
// Force switch to tab 0 if active tab was an unpinned temp tab or
// index is now out of range. Pinned tabs survive — no switch needed.
var stillValid = lastIndex >= 0 && lastIndex < Plugin.Config.Tabs.Count;
if (currentWasUnpinnedTempTab || !stillValid)
// HandleTell builds a tab outside the lock; bumping here lets it detect
// that the world moved on and drop what it built. Read and compared under
// the same lock, so no volatile needed.
_tabGeneration++;
// Re-anchor the UI selection if the active tab was one of the stripped
// unpinned temp tabs (reference predicate, not an index). Logout is a
// framework-thread event, so this is already serialized with Draw — no
// marshalling needed here, unlike the worker-thread eviction path.
if (active is { } a && TabLifecycleHelpers.IsInUnpinnedPool(a))
{
_plugin.WantedTab = 0;
_plugin.MainWindow?.ResetActiveTabIfRemoved(a);
}
}
}
@@ -470,16 +575,23 @@ internal sealed class AutoTellTabsService : IDisposable
return false;
}
if (PinnedTempTabCount >= MaxPinnedTempTabs)
// Count and flag under one lock so the cap can't be raced. SaveConfig stays
// OUTSIDE -- holding TabsListLock across a save would put an fsync on the
// click path, which is what a later cycle just removed elsewhere.
lock (TabsListLock)
{
WrapperUtil.AddNotification(
string.Format(HellionStrings.PinTab_LimitReached, MaxPinnedTempTabs),
NotificationType.Warning
);
return false;
if (PinnedTempTabCount >= MaxPinnedTempTabs)
{
WrapperUtil.AddNotification(
string.Format(HellionStrings.PinTab_LimitReached, MaxPinnedTempTabs),
NotificationType.Warning
);
return false;
}
tab.IsPinned = true;
}
tab.IsPinned = true;
_logger.LogDebug(
$"[Pin] Pinned tab '{tab.Name}' target={tab.TellTarget?.Name}@{tab.TellTarget?.World}"
);
@@ -496,13 +608,18 @@ internal sealed class AutoTellTabsService : IDisposable
// If the unpinned pool is already full, dropping the oldest before
// flipping the flag avoids counting the just-unpinned tab as a drop
// candidate.
if (ActiveTempTabCount >= Plugin.Config.AutoTellTabsLimit)
// candidate. Under lock, since DropOldestTempTab mutates the list.
// SaveConfig stays outside, see TryPin.
lock (TabsListLock)
{
DropOldestTempTab();
if (ActiveTempTabCount >= Plugin.Config.AutoTellTabsLimit)
{
DropOldestTempTab();
}
tab.IsPinned = false;
}
tab.IsPinned = false;
_logger.LogDebug("[Pin] Unpinned tab '{TabName}'", tab.Name);
_plugin.SaveConfig();
}
@@ -514,9 +631,17 @@ internal sealed class AutoTellTabsService : IDisposable
return;
}
tab.IsTempTab = false;
tab.IsPinned = false;
tab.TellTarget = TellTarget.Empty();
// Drops the temp/pin flags, the persisted tell target AND the runtime
// channel's tell state. The runtime-channel clear is the CORR-1 guard —
// see StripTellBindingOnPromote; clearing Tab.TellTarget alone would leave
// CurrentChannel.Channel == Tell + a stale target and route a typed line
// silently as /tell to the old partner.
// Flips IsTempTab/IsPinned, which decide pool membership and whether a save
// strips the tab. Under lock so a concurrent save sees one or the other, never
// half. SaveConfig stays outside, see TryPin.
lock (TabsListLock)
TabLifecycleHelpers.StripTellBindingOnPromote(tab);
_logger.LogDebug($"[Pin] Promoted tab '{tab.Name}' to permanent (tell-binding dropped)");
_plugin.SaveConfig();
}
+3
View File
@@ -10,6 +10,8 @@ internal static class BrandingLinks
public const string HellionForgeGitea = "https://gitea.hellion-forge.cloud/Hellion-Forge";
public const string HellionChatRepo =
"https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat";
public const string HellionChatCustomRepoManifest =
"https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/raw/branch/main/repo.json";
public const string HellionForgeWebsite = "https://hellion-forge.cloud";
public const string HellionMediaWebsite = "https://hellion-media.de/de";
@@ -26,6 +28,7 @@ internal static class BrandingLinks
HellionForgeDiscordInvite,
HellionForgeGitea,
HellionChatRepo,
HellionChatCustomRepoManifest,
HellionForgeWebsite,
HellionMediaWebsite
);
+26
View File
@@ -0,0 +1,26 @@
namespace HellionChat;
// Reduced CJK fallback coverage for the v1.5.3 NotoSansCjk fallback merge.
// Before that the fallback merged over the full `Ranges` array (Default + endonyms),
// duplicating the Latin/Default work already done by the global/Japanese fonts.
// This is the trimmed remainder the fallback is actually the sole source for:
// - Hangul Syllables (AC00-D7A3): no other merged font ships Korean glyphs.
// - The full CJK Unified Ideographs (Han) block: at UseHellionFont=true the global
// font is Inter-Light (no CJK), so the fallback is the SOLE Han source. The JpRange
// overlap is harmless (MergeMode: the Japanese font wins for shared kanji).
// Deliberately excluded: ONLY the ASCII/Latin Default block (0x20-0xFF), which the
// global font already owns -- that doubled Latin merge is the waste being removed.
// Kept as plain start/end pairs so it is unit-testable without the unsafe ImGui
// glyph-range builder (mirrors FontSizeResolver's split-for-test rationale).
internal static class CjkFallbackRange
{
// Hangul Syllables + the full CJK Unified Ideographs (Han) block. Rationale: see
// class comment. Plain start/end pairs so it stays unit-testable.
internal static readonly ushort[] Pairs =
[
0xAC00,
0xD7A3, // Hangul Syllables
0x4E00,
0x9FFF, // CJK Unified Ideographs (full Han) -- sole source at UseHellionFont
];
}
+216 -202
View File
@@ -35,7 +35,7 @@ public class ConfigKeyBind
[Serializable]
public class Configuration : IPluginConfiguration
{
private const int LatestVersion = 19;
internal const int LatestVersion = 27;
public int Version { get; set; } = LatestVersion;
@@ -45,21 +45,29 @@ public class Configuration : IPluginConfiguration
// Global window opacity, applied across all themes.
public float WindowOpacity = 0.85f;
// UI-12: background opacity of the main chat window while unfocused.
// Background opacity of the main chat window while unfocused.
// WindowOpacity above stays the focused value.
public float WindowOpacityInactive = 0.65f;
public float WindowOpacityInactive = 0.75f;
// Reserved for future UI toggles; pre-declared to avoid a migration later.
public bool ReduceMotion;
// v1.2.1: default flipped false → true. Compact single-line layout is
// more readable than the card-rows layout introduced in v1.2.0.
public bool UseCompactDensity = true;
public bool UseCompactDensity;
// Privacy by Default master switch. Set false to restore upstream behaviour.
public bool PrivacyFilterEnabled = true;
// Empty set means the migration has not run yet — see Plugin.cs v6→v7.
// Stays empty here. Dalamud deserialises with Json.NET's default settings,
// which means ObjectCreationHandling.Auto: a collection field that already
// holds items is *populated*, not replaced. A non-empty initializer would
// therefore union itself into every config on load and switch channels the
// user had unticked back on. Verified against Newtonsoft 13.0.3:
// saved [] loads as the initializer, saved [Say] loads as initializer + Say.
//
// Privacy by Default (DSGVO Art. 25) is seeded in CreateFresh instead, which
// only runs when there is no config file at all.
public HashSet<ChatType> PrivacyPersistChannels = [];
// Failsafe for ChatTypes added by future FFXIV patches. New configs default
@@ -69,24 +77,39 @@ public class Configuration : IPluginConfiguration
.PrivacyDefaults
.DefaultPersistUnknownChannels;
// F3.2: dedup unknown-ChatType warnings so a chatty filter doesn't spam
// Dedup unknown-ChatType warnings so a chatty filter doesn't spam
// the log every frame. NonSerialized so the warning fires once per
// runtime, not once-ever-per-install.
[NonSerialized]
private readonly HashSet<ChatType> _warnedUnknownChannels = new();
// A first-ever start records the player's own conversations and nothing
// else. Deliberately not a field initializer -- see PrivacyPersistChannels.
internal static Configuration CreateFresh()
{
var config = new Configuration();
config.PrivacyPersistChannels = [.. Privacy.PrivacyDefaults.PrivacyFirstWhitelist];
return config;
}
public bool IsAllowedForStorage(ChatType type)
{
if (!PrivacyFilterEnabled)
return true;
if (PrivacyPersistChannels.Contains(type))
return true;
// F3.2: log first occurrence of a ChatType the running build doesn't
// recognise — i.e. one a future FFXIV patch may have added. Known
// types the user opted out of are routed through the failsafe
// silently, like before.
if (!Enum.IsDefined(typeof(ChatType), type) && _warnedUnknownChannels.Add(type))
// Runs per message on the worker thread while the settings UI can Add to the
// same set from the draw thread. A HashSet.Contains racing an Add that
// resizes buckets can return the wrong answer -- and this answer decides
// whether a message is persisted. Lock kept tight, this is a hot path.
bool listed;
lock (Plugin.Instance.ConfigMapsLock)
listed = PrivacyPersistChannels.Contains(type);
var known = Enum.IsDefined(typeof(ChatType), type);
// Log the first occurrence of a ChatType the running build doesn't
// recognise — i.e. one a future FFXIV patch may have added.
if (!known && !listed && _warnedUnknownChannels.Add(type))
{
Plugin.LogProxy.Warning(
"PrivacyFilter: unrecognised ChatType {Type} — falling back to PrivacyPersistUnknownChannels={Persist}.",
@@ -95,7 +118,7 @@ public class Configuration : IPluginConfiguration
);
}
return PrivacyPersistUnknownChannels;
return Privacy.StorageRule.Allows(listed, known, PrivacyPersistUnknownChannels);
}
// Retention master switch defaults to false — plugin will not delete
@@ -122,23 +145,31 @@ public class Configuration : IPluginConfiguration
// who don't care, and dodges the per-frame DrawList overhead on low-end
// hardware. Gradient (Color3 / GradientColourSet) is parsed but rendered
// as the primary Color until a later cycle ports the animation.
public bool ShowHonorificGlow;
public bool ShowHonorificGlow = true;
public bool EnableAutoTellTabs = true;
public int AutoTellTabsLimit = 15;
public bool AutoTellTabsCompactDisplay;
public int AutoTellTabsHistoryPreload = 20;
public bool AutoTellTabsCompactDisplay = true;
public int AutoTellTabsHistoryPreload = 100;
// Sidebar width in pixels. Default 44 mirrors the icon-only layout from
// v1.2.0; users can widen up to 160 to fit a section-header line like
// "Active Tells (3)" without truncation.
public int SidebarWidth = 44;
// Expanded sidebar width in pixels. 44 was carried over from the v1.2.0
// icon-only layout and stayed the default long after the sidebar started
// drawing labels beside those icons, so every tab name came out clipped --
// it only went unnoticed because everyone had widened it by hand. 160 fits
// the German tab names, which are the longest of the 25 languages, and the
// floor below is set where they stop being readable rather than where the
// icons stop fitting.
public int SidebarWidth = 160;
public bool AutoTellTabsShowGreetedToggle;
public bool SeenPopOutInputHint;
public bool PopOutInputEnabled = true;
public bool SeenPopOutHeaderHint;
public bool AutoTellTabsOpenAsPopout;
// UI-7: how sender names are rendered in the chat log.
// On by default: the wizard's closing step tells the user to try /tell and
// watch a conversation open on its own, so the behaviour it describes has to
// be the behaviour they get.
public bool AutoTellTabsOpenAsPopout = true;
// How sender names are rendered in the chat log.
public WorldSuffixMode WorldSuffixMode = WorldSuffixMode.OtherWorldOnly;
public NameFormMode NameFormMode = NameFormMode.Full;
@@ -161,35 +192,41 @@ public class Configuration : IPluginConfiguration
// v1.2.1: default flipped false → true for consistency with other hide defaults.
public bool HideInNewGamePlusMenu = true;
public bool HideWhenInactive;
public int InactivityHideTimeout = 10;
public bool InactivityHideActiveDuringBattle = true;
[Obsolete("Use InactivityHideChannelsV2 instead")]
public Dictionary<ChatType, ChatSource> InactivityHideChannels = [];
public Dictionary<ChatType, (ChatSource, ChatSource)> InactivityHideChannelsV2 = [];
public bool InactivityHideExtraChatAll = true;
public HashSet<Guid> InactivityHideExtraChatChannels = [];
public bool ShowHideButton = true;
public bool NativeItemTooltips = true;
public bool ScreenshotMode;
// No control and no reader. Kept so a stored value survives until the
// rendering they describe exists; see the reconnect backlog. Note the two
// resource sets disagree on what PrettierTimestamps even means -- the wizard
// called it "relative time", the settings tab "modern layout".
public bool PrettierTimestamps = true;
public bool MoreCompactPretty;
public bool MoreCompactPretty = true;
public bool HideSameTimestamps = true;
// No reader; see the reconnect backlog.
public bool ShowNoviceNetwork;
// Migration-only since v23: the 1.5.6 sidebar↔top-tabs switch, superseded by
// MainWindowLayoutMode in the v1.6.0 rewrite. No UI control anymore; read by
// the v23 migration in Plugin.cs and kept deserializable so a 1.5.6 user's
// false value survives one load. Remove in a later schema bump.
public bool SidebarTabView = true;
// No reader; see the reconnect backlog.
public bool PrintChangelog = true;
public bool OnlyPreviewIf;
public int PreviewMinimum = 1;
public PreviewPosition PreviewPosition = PreviewPosition.Inside;
public CommandHelpSide CommandHelpSide = CommandHelpSide.None;
public CommandHelpSide CommandHelpSide = CommandHelpSide.Right;
public KeybindMode KeybindMode = KeybindMode.Strict;
public LanguageOverride LanguageOverride = LanguageOverride.None;
public bool CanMove = true;
public bool CanResize = true;
public bool ShowTitleBar = true;
public bool ShowTitleBar;
public bool ShowPopOutTitleBar = true;
public bool DatabaseBattleMessages;
public bool LoadPreviousSession;
public bool FilterIncludePreviousSessions;
public bool SortAutoTranslate;
public bool CollapseDuplicateMessages;
@@ -203,13 +240,10 @@ public class Configuration : IPluginConfiguration
// Toast when a tell the user sent could not be delivered.
public bool NotifyFailedTell = true;
// UI-11: warn before sending a message that carries plugin-only glyphs.
// Warn before sending a message that carries plugin-only glyphs.
public bool NotifyPluginDisclosure = true;
public bool KeepInputFocus = true;
public int MaxLinesToRender = 2_500; // 1-10000
public bool Use24HourClock = true;
public bool ShowEmotes = true;
public HashSet<string> BlockedEmotes = [];
public bool FontsEnabled = true;
public ExtraGlyphRanges ExtraGlyphRanges = 0;
public float FontSizeV2 = 12.75f;
@@ -246,153 +280,66 @@ public class Configuration : IPluginConfiguration
return defaults;
}
// No reader; see the reconnect backlog.
public bool ColorSelectedInputChannelButton = true;
public List<Tab> Tabs = [];
public ConfigKeyBind? ChatTabForward;
public ConfigKeyBind? ChatTabBackward;
public void UpdateFrom(Configuration other, bool backToOriginal)
{
if (backToOriginal)
foreach (var tab in Tabs.Where(t => t.PopOut))
tab.PopOut = false;
// v20 fields: window visibility state, channel popout pool size and
// sidebar auto-switch threshold. All initializers double as the
// migration defaults for configs loaded at v19 or earlier.
// Still written on open/close, but no longer read for the start state: the
// window always shows on login (1.5.6 parity, MainWindow ctor). Kept for the
// migration round-trip and a possible future "remember session state" opt-in.
public bool MainWindowOpen = true;
public bool SettingsWindowOpen;
public int MaxParallelPopouts = 8;
public TellAutoOpenMode TellAutoOpenMode = TellAutoOpenMode.Sidebar;
HideChat = other.HideChat;
HideDuringCutscenes = other.HideDuringCutscenes;
HideWhenNotLoggedIn = other.HideWhenNotLoggedIn;
HideWhenUiHidden = other.HideWhenUiHidden;
HideInLoadingScreens = other.HideInLoadingScreens;
HideInBattle = other.HideInBattle;
HideInNewGamePlusMenu = other.HideInNewGamePlusMenu;
HideWhenInactive = other.HideWhenInactive;
InactivityHideTimeout = other.InactivityHideTimeout;
InactivityHideActiveDuringBattle = other.InactivityHideActiveDuringBattle;
InactivityHideChannelsV2 = other.InactivityHideChannelsV2.ToDictionary(
pair => pair.Key,
pair => pair.Value
);
InactivityHideExtraChatAll = other.InactivityHideExtraChatAll;
InactivityHideExtraChatChannels = other.InactivityHideExtraChatChannels.ToHashSet();
ShowHideButton = other.ShowHideButton;
NativeItemTooltips = other.NativeItemTooltips;
PrettierTimestamps = other.PrettierTimestamps;
MoreCompactPretty = other.MoreCompactPretty;
HideSameTimestamps = other.HideSameTimestamps;
ShowNoviceNetwork = other.ShowNoviceNetwork;
SidebarTabView = other.SidebarTabView;
PrintChangelog = other.PrintChangelog;
OnlyPreviewIf = other.OnlyPreviewIf;
PreviewMinimum = other.PreviewMinimum;
PreviewPosition = other.PreviewPosition;
CommandHelpSide = other.CommandHelpSide;
KeybindMode = other.KeybindMode;
LanguageOverride = other.LanguageOverride;
CanMove = other.CanMove;
CanResize = other.CanResize;
ShowTitleBar = other.ShowTitleBar;
ShowPopOutTitleBar = other.ShowPopOutTitleBar;
DatabaseBattleMessages = other.DatabaseBattleMessages;
LoadPreviousSession = other.LoadPreviousSession;
FilterIncludePreviousSessions = other.FilterIncludePreviousSessions;
SortAutoTranslate = other.SortAutoTranslate;
CollapseDuplicateMessages = other.CollapseDuplicateMessages;
CollapseKeepUniqueLinks = other.CollapseKeepUniqueLinks;
SymbolPickerEnabled = other.SymbolPickerEnabled;
PlaySounds = other.PlaySounds;
CustomSoundVolume = other.CustomSoundVolume;
NotifyFailedTell = other.NotifyFailedTell;
NotifyPluginDisclosure = other.NotifyPluginDisclosure;
KeepInputFocus = other.KeepInputFocus;
MaxLinesToRender = other.MaxLinesToRender;
Use24HourClock = other.Use24HourClock;
ShowEmotes = other.ShowEmotes;
// Deep-copy so settings window edits don't leak into live config before Save.
BlockedEmotes = new HashSet<string>(other.BlockedEmotes);
FontsEnabled = other.FontsEnabled;
ItalicEnabled = other.ItalicEnabled;
ExtraGlyphRanges = other.ExtraGlyphRanges;
FontSizeV2 = other.FontSizeV2;
GlobalFontV2 = other.GlobalFontV2;
JapaneseFontV2 = other.JapaneseFontV2;
ItalicFontV2 = other.ItalicFontV2;
SymbolsFontSizeV2 = other.SymbolsFontSizeV2;
TooltipOffset = other.TooltipOffset;
ChatColours = other.ChatColours.ToDictionary(entry => entry.Key, entry => entry.Value);
ColorSelectedInputChannelButton = other.ColorSelectedInputChannelButton;
// When true (default) the tell-auto-open router switches the active tab to the
// incoming tell on every message; when false the tab is still created/revealed
// with its unread badge but the active tab is left where the user is reading.
public bool TellAutoOpenSwitchAlways = true;
public int SidebarAutoSwitchThresholdPx = 800;
// Keep live temp tabs alive across UpdateFrom — a settings save must
// not destroy open tell conversations. Pinned TempTabs are persistent
// and come through `other` like regular tabs; unpinned TempTabs are
// session-only and held from the local state. For persistent tabs
// (incl. pinned), capture live runtime state by Identifier and restore
// it onto the freshly cloned tabs — CurrentChannel is critical because
// the user may have switched channel in-game between settings-open
// and settings-save, and we'd otherwise overwrite that with the
// settings-time snapshot.
var liveUnpinnedTempTabs = Tabs.Where(TabLifecycleHelpers.IsInUnpinnedPool).ToList();
var livePersistentSession = Tabs.Where(t => !TabLifecycleHelpers.IsInUnpinnedPool(t))
.ToDictionary(t => t.Identifier, t => (t.Messages, t.LastSendUnread, t.CurrentChannel));
// v22 field: MainWindow layout mode (sidebar vs. horizontal top tabs).
// Initializer doubles as the migration default for configs loaded at v21.
public MainWindowLayoutMode MainWindowLayoutMode = MainWindowLayoutMode.Sidebar;
}
Tabs = other
.Tabs.Where(t => !t.IsTempTab || t.IsPinned)
.Select(t =>
{
var clone = t.Clone();
if (livePersistentSession.TryGetValue(clone.Identifier, out var live))
{
clone.Messages = live.Messages;
clone.LastSendUnread = live.LastSendUnread;
clone.CurrentChannel = live.CurrentChannel;
}
return clone;
})
.ToList();
Tabs.AddRange(liveUnpinnedTempTabs);
[Serializable]
public enum TellAutoOpenMode
{
Off,
Sidebar,
TopTab,
Popout,
}
ChatTabForward = other.ChatTabForward;
ChatTabBackward = other.ChatTabBackward;
public static class TellAutoOpenModeExt
{
// The only display name set still in English. It sat inline in ChannelsTab
// as a literal array, which is why it was missed when the rest moved into
// resources; here it is at least in the same place as its peers for the
// localisation pass to pick up.
public static string Name(this TellAutoOpenMode mode) =>
mode switch
{
TellAutoOpenMode.Off => "Off",
TellAutoOpenMode.Sidebar => "Sidebar",
TellAutoOpenMode.TopTab => "Top tab",
TellAutoOpenMode.Popout => "Popout",
_ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null),
};
}
PrivacyFilterEnabled = other.PrivacyFilterEnabled;
PrivacyPersistChannels = [.. other.PrivacyPersistChannels];
PrivacyPersistUnknownChannels = other.PrivacyPersistUnknownChannels;
RetentionEnabled = other.RetentionEnabled;
RetentionDefaultDays = other.RetentionDefaultDays;
RetentionPerChannelDays = other.RetentionPerChannelDays.ToDictionary(
p => p.Key,
p => p.Value
);
RetentionLastRunAt = other.RetentionLastRunAt;
FirstRunCompleted = other.FirstRunCompleted;
WizardLastShownVersion = other.WizardLastShownVersion;
UseHellionFont = other.UseHellionFont;
ShowHonorificTitleInHeader = other.ShowHonorificTitleInHeader;
ShowHonorificGlow = other.ShowHonorificGlow;
// v1.1.0 theme engine fields
Theme = other.Theme;
WindowOpacity = other.WindowOpacity;
WindowOpacityInactive = other.WindowOpacityInactive;
ReduceMotion = other.ReduceMotion;
UseCompactDensity = other.UseCompactDensity;
EnableAutoTellTabs = other.EnableAutoTellTabs;
AutoTellTabsLimit = other.AutoTellTabsLimit;
AutoTellTabsCompactDisplay = other.AutoTellTabsCompactDisplay;
AutoTellTabsHistoryPreload = other.AutoTellTabsHistoryPreload;
SidebarWidth = other.SidebarWidth;
AutoTellTabsShowGreetedToggle = other.AutoTellTabsShowGreetedToggle;
SeenPopOutInputHint = other.SeenPopOutInputHint;
PopOutInputEnabled = other.PopOutInputEnabled;
SeenPopOutHeaderHint = other.SeenPopOutHeaderHint;
AutoTellTabsOpenAsPopout = other.AutoTellTabsOpenAsPopout;
WorldSuffixMode = other.WorldSuffixMode;
NameFormMode = other.NameFormMode;
}
[Serializable]
public enum MainWindowLayoutMode
{
Sidebar,
TopTabs,
}
[Serializable]
@@ -432,9 +379,6 @@ public class Tab
// Optional FontAwesome glyph name; null falls back to TabIconMapping default.
public string? Icon = null;
[Obsolete("Removed in favor of SelectedChannels")]
public Dictionary<ChatType, ChatSource> ChatCodes = new();
public Dictionary<ChatType, (ChatSource, ChatSource)> SelectedChannels = new();
public bool ExtraChatAll;
public HashSet<Guid> ExtraChatChannels = [];
@@ -451,23 +395,33 @@ public class Tab
public bool CanMove = true;
public bool CanResize = true;
public bool IndependentHide;
public bool HideDuringCutscenes = true;
public bool HideWhenNotLoggedIn = true;
public bool HideWhenUiHidden = true;
public bool HideInLoadingScreens;
public bool HideInBattle;
// Six per-tab hide conditions used to live here. Their reader was the
// pop-out window, which stopped consulting them in cf4705e; the equivalents
// that survive are the window-level fields of the same name further up this
// file, and v1.12.0 gave every one of those a control.
//
// Per-tab was the wrong unit anyway: "hide during cutscenes" is a statement
// about the screen, not about one conversation.
//
// HideWhenInactive stays -- the auto-tell service writes it.
public bool HideWhenInactive;
public bool IsTempTab;
// Pinned TempTabs survive plugin reload and logout — tester feedback from
// Jin (v1.4.7). Pinned tabs live in their own pool (MaxPinnedTempTabs)
// separate from the AutoTellTabsLimit bucket.
// Pinned TempTabs survive plugin reload and logout -- tester feedback in
// v1.4.7. Pinned tabs live in their own pool (MaxPinnedTempTabs) separate
// from the AutoTellTabsLimit bucket.
public bool IsPinned;
public bool AllSenderMessages;
public TellTarget TellTarget = TellTarget.Empty();
// Set once, where the name is built from a conversation partner. Never
// cleared by promotion, unlike IsTempTab and TellTarget -- both of those are
// routing state and are deliberately wiped when a tab is promoted, while the
// name they produced stays. Screenshot mode reads this, so it has to outlive
// every path that keeps the name but drops the binding.
public bool NameCameFromPartner;
// Per-tab notification sound for messages arriving in an inactive tab.
public bool EnableNotificationSound;
public uint NotificationSoundId = 1;
@@ -514,7 +468,7 @@ public class Tab
[NonSerialized]
internal string? _cachedTellIcon;
// PM-3 hover-lerp state. Default 0f means "not hovered". Sidebar
// hover-lerp state. Default 0f means "not hovered". Sidebar
// path animates per tab; card-mode-border path is tab-aggregate
// (any card-row hover ramps the alpha for all cards in this tab).
// Lerp speed lives in the render loop, not here, so the same field
@@ -525,6 +479,34 @@ public class Tab
[NonSerialized]
internal float _cardHoverAlpha;
// Copy-on-write for the three channel-filter fields. They are read without
// any lock from the pending-message thread, the filter worker and the draw
// thread, and until v1.12.0 nothing ever wrote them after load -- so the
// tab editor is their first writer, and mutating a live Dictionary while
// Matches enumerates it is the classic way to get a wrong answer or an
// exception on somebody else's thread.
//
// Building the replacements and swapping the references means a reader sees
// either the old set or the new one, never half of either.
//
// What this deliberately does not do is make the three writes one atomic
// step. A reader can catch the new dictionary with the old ExtraChat flag
// for a single message. That is harmless: the editor finishes by clearing
// and refiltering every tab, so any message placed by a mixed view is
// reconsidered a moment later. Making it truly atomic would mean one
// reference for all three, and these three are serialized fields with a
// shape the config file already has.
internal void ReplaceChannelFilter(
Dictionary<ChatType, (ChatSource, ChatSource)> selected,
bool extraChatAll,
HashSet<Guid> extraChatChannels
)
{
Volatile.Write(ref SelectedChannels, selected);
Volatile.Write(ref ExtraChatChannels, extraChatChannels);
Volatile.Write(ref ExtraChatAll, extraChatAll);
}
public bool Matches(Message message)
{
if (!message.Matches(SelectedChannels, ExtraChatAll, ExtraChatChannels))
@@ -545,14 +527,14 @@ public class Tab
return;
Unread += 1;
if (
message.Matches(
Plugin.Config.InactivityHideChannelsV2,
Plugin.Config.InactivityHideExtraChatAll,
Plugin.Config.InactivityHideExtraChatChannels
)
)
LastActivity = Environment.TickCount64;
// Stamped for every message now. The condition that used to sit here
// filtered on InactivityHideChannels, a setting for the hide-when-
// inactive feature -- and that feature lost its reader in cf4705e. So
// which tell tab the auto-tell pool drops first, which is the only
// thing that reads this stamp, hung on a setting for something that
// does not happen.
LastActivity = Environment.TickCount64;
}
public void Clear() => Messages.Clear();
@@ -562,6 +544,11 @@ public class Tab
return new Tab
{
Name = Name,
// Icon feeds the sidebar glyph and a clone round-trip used to drop
// it silently. ChatCodes sat beside it until v1.12.0, carrying data
// for a migration that the v16 schema gate had already made
// unreachable.
Icon = Icon,
SelectedChannels = SelectedChannels.ToDictionary(pair => pair.Key, pair => pair.Value),
ExtraChatAll = ExtraChatAll,
ExtraChatChannels = ExtraChatChannels.ToHashSet(),
@@ -579,12 +566,6 @@ public class Tab
CurrentChannel = CurrentChannel.Clone(),
CanMove = CanMove,
CanResize = CanResize,
IndependentHide = IndependentHide,
HideDuringCutscenes = HideDuringCutscenes,
HideWhenNotLoggedIn = HideWhenNotLoggedIn,
HideWhenUiHidden = HideWhenUiHidden,
HideInLoadingScreens = HideInLoadingScreens,
HideInBattle = HideInBattle,
HideWhenInactive = HideWhenInactive,
IsTempTab = IsTempTab,
IsPinned = IsPinned,
@@ -969,6 +950,39 @@ public static class LanguageOverrideExt
// Mutable.ExtraGlyphRanges so users do not need to know which range
// to tick manually. Returns 0 for locales fully covered by the default
// ImGui glyph range (Latin-1) or by the separate Japanese font handle.
// The same mapping keyed by culture code, for when the language override is
// None and the UI follows Dalamud. Without this the ranges only ever get
// filled by an explicit language pick -- installs that never touched the
// setting rendered their own locale in whatever the default range covers,
// which for Korean, Chinese, Cyrillic and Greek is boxes. It went unnoticed
// while configs accumulated ranges over time; a fresh config has none.
public static ExtraGlyphRanges RequiredGlyphRangesForCulture(string? cultureCode)
{
var code = (cultureCode ?? string.Empty).ToLowerInvariant();
// Longest first: zh-hant has to win over the zh prefix.
if (code.StartsWith("zh-hant") || code.StartsWith("zh-tw") || code.StartsWith("zh-hk"))
return ExtraGlyphRanges.ChineseFull;
if (code.StartsWith("zh"))
return ExtraGlyphRanges.ChineseSimplifiedCommon;
if (code.StartsWith("ko"))
return ExtraGlyphRanges.Korean;
if (code.StartsWith("uk") || code.StartsWith("ru") || code.StartsWith("be"))
return ExtraGlyphRanges.Cyrillic;
if (code.StartsWith("el"))
return ExtraGlyphRanges.Greek;
if (
code.StartsWith("cs")
|| code.StartsWith("pl")
|| code.StartsWith("ro")
|| code.StartsWith("hu")
|| code.StartsWith("tr")
)
return ExtraGlyphRanges.LatinExtended;
return 0;
}
public static ExtraGlyphRanges RequiredGlyphRanges(this LanguageOverride mode) =>
mode switch
{
-418
View File
@@ -1,418 +0,0 @@
using System.Collections.Concurrent;
using System.Numerics;
using System.Text.Json;
using System.Text.Json.Serialization;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Textures;
using Dalamud.Interface.Textures.TextureWraps;
using Dalamud.Utility;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
namespace HellionChat;
public static class EmoteCache
{
private static readonly string[] NotWorking =
[
":tf:",
"(ditto)",
"c!",
"h!",
"l!",
"M&Mjc",
"LUL3D",
"p!",
"POLICE2",
"r!",
"Pussy",
"s!",
"v!",
"w!",
"x0r6ztGiggle",
"z!",
"xar2EDM",
"iron95Pls",
"Clap2",
"AlienPls3",
"Life",
"peepoPogClimbingTreeHard4House",
"monkaGIGAftRobertDowneyJr",
"DogLookingSussyAndCold",
"DICKS",
];
private static readonly HttpClient Client = new();
private const string BetterTTV = "https://api.betterttv.net/3";
private const string GlobalEmotes = $"{BetterTTV}/cached/emotes/global";
private const string Top100Emotes = "{0}/emotes/shared/top?before={1}&limit=100";
private const string EmotePath = "https://cdn.betterttv.net/emote/{0}/3x";
[Serializable]
private struct Top100()
{
[JsonPropertyName("emote")]
public Emote Emote { get; set; }
[JsonPropertyName("id")]
public required string Id { get; set; }
}
[Serializable]
public struct Emote()
{
[JsonPropertyName("id")]
public required string Id { get; set; }
[JsonPropertyName("code")]
public required string Code { get; set; }
[JsonPropertyName("imageType")]
public required string ImageType { get; set; }
}
public enum LoadingState
{
Unloaded,
Loading,
Done,
}
// All fields below are uninitialised while State != Done.
public static LoadingState State = LoadingState.Unloaded;
private static readonly Dictionary<string, Emote> Cache = new();
private static readonly Dictionary<string, EmoteBase> EmoteImages = new();
public static string[] SortedCodeArray = [];
// Cancelled on Dispose to stop in-flight downloads; replaced on re-enable.
private static CancellationTokenSource Cts = new();
internal static CancellationToken Token => Cts.Token;
// Tracks in-flight loads so Dispose can drain them before teardown.
private static readonly ConcurrentBag<Task> PendingLoads = new();
internal static void TrackLoad(Task loadTask, string emoteCode)
{
PendingLoads.Add(
loadTask.ContinueWith(
t =>
{
if (t.IsFaulted)
Plugin.LogProxy.Error(
t.Exception!,
$"EmoteCache load failed for {emoteCode}"
);
},
TaskScheduler.Default
)
);
}
public static async Task LoadData()
{
if (State is not LoadingState.Unloaded)
return;
// Reset CTS if Dispose was called and the plugin is being re-enabled.
if (Cts.IsCancellationRequested)
Cts = new CancellationTokenSource();
State = LoadingState.Loading;
var ct = Cts.Token;
try
{
var global = await Client.GetAsync(GlobalEmotes, ct);
var globalList = await global.Content.ReadAsStringAsync(ct);
foreach (var emote in JsonSerializer.Deserialize<Emote[]>(globalList)!)
if (!string.IsNullOrEmpty(emote.Code) && !NotWorking.Contains(emote.Code))
Cache.TryAdd(emote.Code, emote);
var lastId = string.Empty;
for (var i = 0; i < 15; i++)
{
var top = await Client.GetAsync(Top100Emotes.Format(BetterTTV, lastId), ct);
var topList = await top.Content.ReadAsStringAsync(ct);
var jsonList = JsonSerializer.Deserialize<List<Top100>>(topList)!;
// BetterTTV occasionally returns entries with a null Code;
// skip them so a single bad row doesn't break the whole cache.
foreach (var emote in jsonList)
if (
!string.IsNullOrEmpty(emote.Emote.Code)
&& !NotWorking.Contains(emote.Emote.Code)
)
Cache.TryAdd(emote.Emote.Code, emote.Emote);
lastId = jsonList.Last().Id;
}
SortedCodeArray = Cache.Keys.Order().ToArray();
State = LoadingState.Done;
}
catch (OperationCanceledException)
{
// Plugin disposed mid-load; State stays on Loading so re-enable can retry.
}
catch (Exception ex)
{
// Reset to Unloaded so a later trigger can retry without a plugin reload.
State = LoadingState.Unloaded;
Plugin.LogProxy.Error(ex, "BetterTTV cache wasn't initialized");
}
}
public static void Dispose()
{
Cts.Cancel();
// 5s upper bound; anything still running gets abandoned.
try
{
Task.WaitAll(PendingLoads.ToArray(), TimeSpan.FromSeconds(5));
}
catch (AggregateException)
{
// Faults already logged in TrackLoad.
}
while (PendingLoads.TryTake(out _)) { }
foreach (var emote in EmoteImages.Values)
emote.InnerDispose();
}
internal static bool Exists(string code)
{
return State is LoadingState.Done && SortedCodeArray.Contains(code);
}
internal static EmoteBase? GetEmote(string code)
{
if (State is not LoadingState.Done)
return null;
if (!Cache.TryGetValue(code, out var emoteDetail))
return null;
if (EmoteImages.TryGetValue(emoteDetail.Id, out var emote))
return emote;
try
{
if (emoteDetail.ImageType == "gif")
{
var animatedEmote = new ImGuiGif().Prepare(emoteDetail);
EmoteImages.Add(emoteDetail.Id, animatedEmote);
return animatedEmote;
}
var staticEmote = new ImGuiEmote().Prepare(emoteDetail);
EmoteImages.Add(emoteDetail.Id, staticEmote);
return staticEmote;
}
catch
{
Plugin.LogProxy.Error("Failed to convert");
return null;
}
}
public abstract class EmoteBase
{
public bool Failed;
public bool IsLoaded;
public byte[] RawData = [];
protected IDalamudTextureWrap? Texture;
public virtual void Draw(Vector2 size)
{
ImGui.Image(Texture!.Handle, size);
}
internal async Task<byte[]> LoadAsync(Emote emote, CancellationToken ct)
{
// Path-traversal guard: resolve and verify the candidate path stays
// inside the cache directory before reading or writing.
var dir = Path.GetFullPath(
Path.Join(Plugin.Interface.ConfigDirectory.FullName, "EmoteCacheV1")
);
Directory.CreateDirectory(dir);
var dirPrefix = dir.EndsWith(Path.DirectorySeparatorChar)
? dir
: dir + Path.DirectorySeparatorChar;
var filePath = Path.GetFullPath(Path.Join(dir, $"{emote.Id}.{emote.ImageType}"));
if (!filePath.StartsWith(dirPrefix, StringComparison.Ordinal))
throw new InvalidOperationException(
$"Emote path escapes cache directory: id={emote.Id}, type={emote.ImageType}"
);
if (File.Exists(filePath))
{
RawData = await File.ReadAllBytesAsync(filePath, ct);
}
else
{
var content = await Client.GetAsync(EmotePath.Format(emote.Id), ct);
RawData = await content.Content.ReadAsByteArrayAsync(ct);
await using var stream = new FileStream(
filePath,
FileMode.Create,
FileAccess.Write,
FileShare.Read
);
await stream.WriteAsync(RawData, ct);
}
return RawData;
}
public abstract void InnerDispose();
}
public sealed class ImGuiEmote : EmoteBase
{
public ImGuiEmote Prepare(Emote emote)
{
var ct = EmoteCache.Token;
// Task.Run keeps the sync prefix off the ImGui render thread.
EmoteCache.TrackLoad(Task.Run(() => LoadAsyncTracked(emote, ct), ct), emote.Code);
return this;
}
private async Task LoadAsyncTracked(Emote emote, CancellationToken ct)
{
try
{
var image = await LoadAsync(emote, ct);
if (image.Length <= 0)
return;
ct.ThrowIfCancellationRequested();
Texture = await Plugin.TextureProvider.CreateFromImageAsync(
image,
cancellationToken: ct
);
IsLoaded = true;
}
catch (OperationCanceledException) { }
catch (Exception ex)
{
Failed = true;
Plugin.LogProxy.Error(ex, $"Unable to load {emote.Code} with id {emote.Id}");
}
}
public override void InnerDispose()
{
Texture?.Dispose();
}
}
public sealed class ImGuiGif : EmoteBase
{
private List<(IDalamudTextureWrap Texture, float Delay)> Frames = [];
private float FrameTimer;
private int CurrentFrame;
private ulong GlobalFrameCount;
public override void Draw(Vector2 size)
{
if (Frames.Count == 0)
return;
if (CurrentFrame >= Frames.Count)
{
CurrentFrame = 0;
FrameTimer = -1f;
}
var frame = Frames[CurrentFrame];
if (FrameTimer <= 0.0f)
FrameTimer = frame.Delay;
ImGui.Image(frame.Texture.Handle, size);
if (GlobalFrameCount == Plugin.Interface.UiBuilder.FrameCount)
return;
GlobalFrameCount = Plugin.Interface.UiBuilder.FrameCount;
FrameTimer -= ImGui.GetIO().DeltaTime;
if (FrameTimer <= 0f)
CurrentFrame++;
}
public override void InnerDispose()
{
Frames.ForEach(f => f.Texture.Dispose());
Frames.Clear();
}
public ImGuiGif Prepare(Emote emote)
{
var ct = EmoteCache.Token;
EmoteCache.TrackLoad(Task.Run(() => LoadAsyncTracked(emote, ct), ct), emote.Code);
return this;
}
private async Task LoadAsyncTracked(Emote emote, CancellationToken ct)
{
try
{
var image = await LoadAsync(emote, ct);
if (image.Length <= 0)
return;
using var ms = new MemoryStream(image);
using var img = Image.Load<Rgba32>(ms);
if (img.Frames.Count == 0)
return;
var frames = new List<(IDalamudTextureWrap Tex, float Delay)>();
foreach (var frame in img.Frames)
{
ct.ThrowIfCancellationRequested();
var delay = frame.Metadata.GetGifMetadata().FrameDelay / 100f;
// Match browser behaviour: anything under 20ms rounds up to 100ms.
if (delay < 0.02f)
delay = 0.1f;
var buffer = new byte[4 * frame.Width * frame.Height];
frame.CopyPixelDataTo(buffer);
var tex = await Plugin.TextureProvider.CreateFromRawAsync(
RawImageSpecification.Rgba32(frame.Width, frame.Height),
buffer,
cancellationToken: ct
);
frames.Add((tex, delay));
}
Frames = frames;
IsLoaded = true;
}
catch (OperationCanceledException)
{
// Plugin disposed mid-load; release any partial frames.
foreach (var f in Frames)
f.Texture.Dispose();
Frames = [];
}
catch (Exception ex)
{
Failed = true;
Plugin.LogProxy.Error(ex, $"Unable to load {emote.Code} with id {emote.Id}");
}
}
}
}
+107 -17
View File
@@ -1,6 +1,7 @@
using System.Globalization;
using System.Text;
using HellionChat.Code;
using HellionChat.Util;
namespace HellionChat.Export;
@@ -33,9 +34,23 @@ internal static class ExportFormatExt
}
// Serializes message snapshots to Markdown, JSON, or CSV.
// Caller handles pre-filtering except sender substring, which requires deserialized SeString.TextValue.
//
// Text comes from the chunk lists, never from SenderSource/ContentSource. Those
// are raw SeStrings, and reading TextValue on one containing an auto-translate
// phrase reaches SeStringEvaluator, which asserts it is on the main thread and
// throws unconditionally when a macro resolves a global number. An export runs on
// a worker, so that would abort it partway and leave half a file behind.
//
// The chunks are already resolved: ChunkUtil turns auto-translate into text at
// ingest, and the full-text index reads them exactly this way. Same strings, no
// evaluator, no thread affinity.
//
// The caller pre-filters by channel and date via StreamForExport; only the sender
// substring is applied here.
internal static class MessageExporter
{
private static readonly UTF8Encoding Utf8NoBom = new(encoderShouldEmitUTF8Identifier: false);
internal record FilterDescription(
IReadOnlyCollection<int>? ChatTypes,
DateTimeOffset? From,
@@ -50,22 +65,83 @@ internal static class MessageExporter
FilterDescription filter
)
{
// Rejected before the file is touched. The old order opened the stream
// first, so an unknown format left a zero-byte file where the user's
// previous export had been.
if (!Enum.IsDefined(format))
throw new ArgumentOutOfRangeException(nameof(format), format, null);
var matching = filter.SenderSubstring is { Length: > 0 } needle
? messages.Where(m => MatchesSender(m, needle))
: messages;
using var writer = new StreamWriter(path, append: false, encoding: Encoding.UTF8);
return format switch
// Written beside the target and moved into place at the end. A crash or
// an unplugged drive halfway through would otherwise leave a file that
// opens fine and is quietly incomplete -- and this is the path a GDPR
// access request goes out on, where "looks complete" is the dangerous
// failure.
var temp = path + ".part";
int written;
try
{
ExportFormat.Markdown => WriteMarkdown(writer, matching, filter),
ExportFormat.Json => WriteJson(writer, matching, filter),
ExportFormat.Csv => WriteCsv(writer, matching, filter),
_ => throw new ArgumentOutOfRangeException(nameof(format), format, null),
};
// Encoding.UTF8 writes a byte order mark, and that is not a
// cosmetic detail here: a leading U+FEFF makes the JSON invalid for
// every strict parser, Python's json.load included. CSV is the one
// format that wants it -- without a BOM Excel guesses the codepage
// and mangles every non-ASCII name in the file.
var encoding = format == ExportFormat.Csv ? Encoding.UTF8 : Utf8NoBom;
using (var writer = new StreamWriter(temp, append: false, encoding))
{
written = format switch
{
ExportFormat.Markdown => WriteMarkdown(writer, matching, filter),
ExportFormat.Json => WriteJson(writer, matching, filter),
_ => WriteCsv(writer, matching, filter),
};
}
// An export that matched nothing does not replace anything. The
// file still has a header and a footer, so moving it would put a
// near-empty file where the user's previous export was -- and then
// report "no message matched the filter", which reads as "nothing
// happened". Dalamud's save dialog has no overwrite confirmation to
// fall back on.
if (written == 0)
{
TryDeleteTemp(temp);
return 0;
}
File.Move(temp, path, overwrite: true);
return written;
}
catch
{
TryDeleteTemp(temp);
throw;
}
}
// Best effort: the export already failed, and a leftover .part file is a
// smaller problem than masking the original exception with an IO one.
private static void TryDeleteTemp(string temp)
{
try
{
if (File.Exists(temp))
File.Delete(temp);
}
catch (IOException) { }
catch (UnauthorizedAccessException) { }
}
private static bool MatchesSender(Message m, string needle) =>
m.SenderSource.TextValue.Contains(needle, StringComparison.OrdinalIgnoreCase);
SenderText(m).Contains(needle, StringComparison.OrdinalIgnoreCase);
private static string SenderText(Message m) => ChunkUtil.ToRawString(m.Sender);
private static string ContentText(Message m) => ChunkUtil.ToRawString(m.Content);
private static int WriteMarkdown(
StreamWriter w,
@@ -94,8 +170,8 @@ internal static class MessageExporter
}
var chatType = (ChatType)(ushort)m.Code.Type;
var sender = m.SenderSource.TextValue.Trim().Trim('<', '>', '[', ']', ':').Trim();
var content = m.ContentSource.TextValue;
var sender = SenderText(m).Trim().Trim('<', '>', '[', ']', ':').Trim();
var content = ContentText(m);
if (string.IsNullOrEmpty(sender))
w.WriteLine($"**[{localDate:HH:mm}] {chatType}:** {content}");
@@ -170,12 +246,17 @@ internal static class MessageExporter
w.Write($",\"date\":\"{m.Date.ToString("O", CultureInfo.InvariantCulture)}\"");
w.Write($",\"chat_type\":{(int)m.Code.Type}");
w.Write($",\"chat_type_name\":\"{chatType}\"");
w.Write($",\"source_kind\":{m.Code.Source}");
w.Write($",\"target_kind\":{m.Code.Target}");
// Cast, not interpolate. These are XivChatRelationKind, and string
// interpolation of an enum writes the member name -- so every
// message with a recognised relation produced
// "source_kind":LocalPlayer, which no parser accepts. This is the
// file an access request goes out on.
w.Write($",\"source_kind\":{(int)m.Code.Source}");
w.Write($",\"target_kind\":{(int)m.Code.Target}");
w.Write($",\"receiver\":{m.Receiver}");
w.Write($",\"content_id\":{m.ContentId}");
w.Write($",\"sender\":{JsonString(m.SenderSource.TextValue)}");
w.Write($",\"content\":{JsonString(m.ContentSource.TextValue)}");
w.Write($",\"sender\":{JsonString(SenderText(m))}");
w.Write($",\"content\":{JsonString(ContentText(m))}");
w.Write("}");
}
@@ -203,9 +284,9 @@ internal static class MessageExporter
w.Write(',');
w.Write(CsvString(chatType.ToString()));
w.Write(',');
w.Write(CsvString(m.SenderSource.TextValue));
w.Write(CsvString(SenderText(m)));
w.Write(',');
w.Write(CsvString(m.ContentSource.TextValue));
w.Write(CsvString(ContentText(m)));
w.Write(',');
w.Write(m.Receiver);
w.Write(',');
@@ -258,8 +339,17 @@ internal static class MessageExporter
private static string CsvString(string s)
{
// Leading =, +, - and @ make a spreadsheet treat the cell as a formula.
// Every value here is text somebody else typed into a chat channel, and
// this file exists to be opened in Excel, so a prefixed apostrophe goes
// in front. It is the standard defence and it costs one character that
// spreadsheets hide.
if (s.Length > 0 && s[0] is '=' or '+' or '-' or '@' or '\t' or '\r')
s = "'" + s;
if (s.IndexOfAny(['"', ',', '\n', '\r']) < 0)
return s;
return "\"" + s.Replace("\"", "\"\"") + "\"";
}
}
+261 -69
View File
@@ -6,6 +6,8 @@ using Dalamud.Interface.GameFonts;
using Dalamud.Interface.ManagedFontAtlas;
using Dalamud.Interface.Utility;
using Dalamud.Plugin;
using HellionChat.Themes;
using HellionChat.Ui.StyleEngine;
namespace HellionChat;
@@ -39,9 +41,70 @@ public sealed class FontManager : IDisposable
internal IFontHandle? RegularFont;
internal IFontHandle? ItalicFont;
// v1.13.0: one handle per type role that needs a face of its own. Sender
// carries extra weight, Meta a smaller size on a tiny glyph range.
internal IFontHandle? SenderFont;
internal IFontHandle? MetaFont;
// The mockup asks for weight 600 on the sender. There is no bold face in the
// plugin and none in the bundled file, so the weight comes from a denser
// rasterisation of the same outline. 1.0 is the SafeFontConfig default;
// below ~1.2 the difference is not visible, above ~1.4 the glyphs smear.
//
// Note on cost: all three delegate handles now carry the full glyph range.
// The meta face started with an ASCII-sized one, on the assumption it would
// only ever draw clocks and world names -- then the channel header wanted
// to use it, and tab names are free user input. An umlaut would have been
// enough to break it.
//
// Not const: the smoke test compares three values side by side, and the
// widget gallery exposes it.
internal static float SenderWeight = 1.3f;
// Wired post-build (B4b-3); a Func keeps FontManager off the theme layer.
private Func<ThemeTypography?>? _typographySource;
// Lets RebuildDelegateFontsIfChanged skip rebuilds when the size is unchanged.
private (
float Global,
float Symbols,
float Sender,
float Meta,
float Italic
) _lastBuiltFingerprint;
// True once every required atlas-owned handle reports Available. Components
// gate their first-frame draw on this — without it the layout math would
// run against placeholder font metrics and snap when the real atlas
// finishes building. ItalicFont being null means italics are disabled in
// config, which is a ready state, not a pending one.
public bool FontsReady =>
Axis.Available
&& AxisItalic.Available
&& FontAwesome.Available
&& RegularFont is { Available: true }
&& (ItalicFont is null || ItalicFont.Available)
// Unconditional, unlike ItalicFont: these two are always built. A handle
// that is not ready yet makes SimplePushedFont push nothing at all --
// silently -- so the first frame after a rebuild would measure the wrong
// face and write those heights into the row cache.
&& SenderFont is { Available: true }
&& MetaFont is { Available: true };
private ushort[] Ranges = [];
private ushort[] JpRange = [];
// Trimmed remainder the NotoSansCjk fallback is the sole source for
// (Hangul + full Han); excludes the Default/Latin block already merged
// by the global font, so the fallback no longer re-merges the full Ranges array.
private ushort[] CjkFallbackGlyphRange = [];
// Report accessor for the ctor self-test: built glyph-range array lengths so
// the step can show the dedup effect (a small trimmed fallback vs the large
// primary range) in its on-disk report instead of a bare Pass.
internal (int Ranges, int JpRange, int CjkFallback) GlyphRangeLengths =>
(Ranges.Length, JpRange.Length, CjkFallbackGlyphRange.Length);
public static readonly HashSet<float> AxisFontSizeList =
[
9.6f,
@@ -91,7 +154,13 @@ public sealed class FontManager : IDisposable
if (Plugin.Config.ItalicEnabled)
ItalicFont = BuildItalicFontHandle(atlas);
SenderFont = BuildSenderFontHandle(atlas);
MetaFont = BuildMetaFontHandle(atlas);
}
// Source is still null here, so this is the config-only baseline.
_lastBuiltFingerprint = EffectiveFontFingerprint();
}
// Called from the settings save path when one of the font-related
@@ -108,25 +177,113 @@ public sealed class FontManager : IDisposable
var atlas = _pluginInterface.UiBuilder.FontAtlas;
RegularFont?.Dispose();
RegularFont = BuildRegularFontHandle(atlas);
// Without the suppression each handle triggers its own atlas rebuild.
// With two handles that was tolerable; with four it is four rebuilds for
// one size change.
using (atlas.SuppressAutoRebuild())
{
RegularFont?.Dispose();
RegularFont = BuildRegularFontHandle(atlas);
ItalicFont?.Dispose();
ItalicFont = Plugin.Config.ItalicEnabled ? BuildItalicFontHandle(atlas) : null;
ItalicFont?.Dispose();
ItalicFont = Plugin.Config.ItalicEnabled ? BuildItalicFontHandle(atlas) : null;
SenderFont?.Dispose();
SenderFont = BuildSenderFontHandle(atlas);
MetaFont?.Dispose();
MetaFont = BuildMetaFontHandle(atlas);
}
_lastBuiltFingerprint = EffectiveFontFingerprint();
}
public void SetTypographySource(Func<ThemeTypography?> source) => _typographySource = source;
internal float ResolveGlobalFontPt() =>
FontSizeResolver.ResolveGlobalPt(
_typographySource?.Invoke(),
Plugin.Config.UseHellionFont,
Plugin.Config.FontSizeV2,
Plugin.Config.GlobalFontV2.SizePt
);
internal float ResolveSymbolsFontPt() =>
FontSizeResolver.ResolveSymbolsPt(
_typographySource?.Invoke(),
Plugin.Config.SymbolsFontSizeV2
);
// Every size that can land in one message row. Roles follow the base size
// arithmetically, but the resolved value is what the height cache has to key
// on -- a theme override moves the base without moving any factor.
internal (
float Global,
float Symbols,
float Sender,
float Meta,
float Italic
) EffectiveFontFingerprint()
{
var basePt = ResolveGlobalFontPt();
return (
basePt,
ResolveSymbolsFontPt(),
TypeScale.SizePtOf(TypeRole.Sender, basePt),
TypeScale.SizePtOf(TypeRole.Meta, basePt),
Plugin.Config.ItalicFontV2.SizePt
);
}
// Rebuilds only when the effective size changed (live fingerprint, TOCTOU-free).
// The atlas rebuild must run on the framework/draw thread — callers ensure that.
internal void RebuildDelegateFontsIfChanged()
{
if (EffectiveFontFingerprint() != _lastBuiltFingerprint)
{
RebuildDelegateFonts();
}
}
// Instance method so Ranges / JpRange are reachable without parameter
// plumbing; PascalCase field names follow the existing class style.
// Shared CJK + symbols tail for both the regular and italic delegate
// fonts. Earlier-merged fonts win for shared codepoints (imgui MergeMode),
// so this runs AFTER the primary font is set as config.MergeFont. The CJK
// fallback is the sole Hangul/Simplified-Han source when UseHellionFont=true
// (global=Inter-Light), so it stays in the chain — only its glyph range is
// trimmed (CjkFallbackGlyphRange) to drop the Default-block/endonym overlap.
// The Japanese merge keeps its own configured size and the full JpRange (which
// owns Traditional Han such as 體 U+9AD4), so japanese↔fallback no longer overlap.
private void AddCjkAndSymbols(
IFontAtlasBuildToolkitPreBuild tk,
SafeFontConfig config,
float basePt
)
{
config.SizePt = Plugin.Config.JapaneseFontV2.SizePt;
config.GlyphRanges = JpRange;
AddFontWithFallback(tk, Plugin.Config.JapaneseFontV2.FontId, config, "japanese");
// NotoSansCjk fallback, trimmed to CjkFallbackGlyphRange. Merged last so earlier fonts win.
config.SizePt = basePt;
config.GlyphRanges = CjkFallbackGlyphRange;
AddFontWithFallback(
tk,
new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkRegular),
config,
"noto-cjk-fallback"
);
config.SizePt = ResolveSymbolsFontPt();
tk.AddGameSymbol(config);
}
private IFontHandle BuildRegularFontHandle(IFontAtlas atlas) =>
atlas.NewDelegateFontHandle(e =>
e.OnPreBuild(tk =>
{
// UseHellionFont swaps the source font but keeps the size
// selector tied to FontSizeV2 (the bundled font ships as
// a single weight).
var basePt = Plugin.Config.UseHellionFont
? Plugin.Config.FontSizeV2
: Plugin.Config.GlobalFontV2.SizePt;
var basePt = ResolveGlobalFontPt();
var config = new SafeFontConfig { SizePt = basePt, GlyphRanges = Ranges };
// Missing embedded resource falls back to the configured
// system font instead of taking the whole UiBuilder down.
@@ -135,25 +292,50 @@ public sealed class FontManager : IDisposable
? tk.AddFontFromMemory(bundledBytes, config, "Inter-Light")
: AddFontWithFallback(tk, Plugin.Config.GlobalFontV2.FontId, config, "global");
config.SizePt = Plugin.Config.JapaneseFontV2.SizePt;
config.GlyphRanges = JpRange;
AddFontWithFallback(tk, Plugin.Config.JapaneseFontV2.FontId, config, "japanese");
AddCjkAndSymbols(tk, config, basePt);
// v1.5.3: NotoSansCjk fallback covers Hangul, Simplified-Chinese
// -specific Han (e.g. 简) and other CJK glyphs that the primary
// (Inter Light / global font) and the FFXIV Japanese font do not
// ship. Merged last so earlier fonts win for shared codepoints.
config.SizePt = basePt;
config.GlyphRanges = Ranges;
AddFontWithFallback(
tk,
new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkRegular),
config,
"noto-cjk-fallback"
);
tk.Font = config.MergeFont;
})
);
config.SizePt = Plugin.Config.SymbolsFontSizeV2;
tk.AddGameSymbol(config);
// Same outline as the body face, rasterised denser. Only works on the
// delegate path: with FontsEnabled and UseHellionFont both off the game's own
// Axis handle draws, and a game font handle has no such knob. The sender then
// leans on channel colour alone, which is a deliberate limitation.
private IFontHandle BuildSenderFontHandle(IFontAtlas atlas) =>
atlas.NewDelegateFontHandle(e =>
e.OnPreBuild(tk =>
{
var basePt = TypeScale.SizePtOf(TypeRole.Sender, ResolveGlobalFontPt());
var config = new SafeFontConfig
{
SizePt = basePt,
GlyphRanges = Ranges,
RasterizerMultiply = SenderWeight,
};
var bundledBytes = Plugin.Config.UseHellionFont ? TryGetBundledFontBytes() : null;
config.MergeFont = bundledBytes is not null
? tk.AddFontFromMemory(bundledBytes, config, "Inter-Light-Sender")
: AddFontWithFallback(tk, Plugin.Config.GlobalFontV2.FontId, config, "sender");
AddCjkAndSymbols(tk, config, basePt);
tk.Font = config.MergeFont;
})
);
private IFontHandle BuildMetaFontHandle(IFontAtlas atlas) =>
atlas.NewDelegateFontHandle(e =>
e.OnPreBuild(tk =>
{
var basePt = TypeScale.SizePtOf(TypeRole.Meta, ResolveGlobalFontPt());
var config = new SafeFontConfig { SizePt = basePt, GlyphRanges = Ranges };
var bundledBytes = Plugin.Config.UseHellionFont ? TryGetBundledFontBytes() : null;
config.MergeFont = bundledBytes is not null
? tk.AddFontFromMemory(bundledBytes, config, "Inter-Light-Meta")
: AddFontWithFallback(tk, Plugin.Config.GlobalFontV2.FontId, config, "meta");
AddCjkAndSymbols(tk, config, basePt);
tk.Font = config.MergeFont;
})
@@ -175,22 +357,7 @@ public sealed class FontManager : IDisposable
"italic"
);
config.SizePt = Plugin.Config.JapaneseFontV2.SizePt;
config.GlyphRanges = JpRange;
AddFontWithFallback(tk, Plugin.Config.JapaneseFontV2.FontId, config, "japanese");
// v1.5.3: NotoSansCjk fallback (see BuildRegularFontHandle).
config.SizePt = Plugin.Config.ItalicFontV2.SizePt;
config.GlyphRanges = Ranges;
AddFontWithFallback(
tk,
new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkRegular),
config,
"noto-cjk-fallback"
);
config.SizePt = Plugin.Config.SymbolsFontSizeV2;
tk.AddGameSymbol(config);
AddCjkAndSymbols(tk, config, Plugin.Config.ItalicFontV2.SizePt);
tk.Font = config.MergeFont;
})
@@ -204,6 +371,8 @@ public sealed class FontManager : IDisposable
// lifetime, so the plugin must not dispose it.
RegularFont?.Dispose();
ItalicFont?.Dispose();
SenderFont?.Dispose();
MetaFont?.Dispose();
}
// Returns null when the embedded font resource is missing. Should not
@@ -234,7 +403,11 @@ public sealed class FontManager : IDisposable
private unsafe void SetUpRanges()
{
ushort[] BuildRange(IReadOnlyList<ushort>? chars, params nint[] ranges)
ushort[] BuildRange(
IReadOnlyList<ushort>? chars,
bool includeCommonExtras,
params nint[] ranges
)
{
var builder = new ImFontGlyphRangesBuilderPtr(ImGuiNative.ImFontGlyphRangesBuilder());
foreach (var range in ranges)
@@ -252,33 +425,43 @@ public sealed class FontManager : IDisposable
}
}
// Ingame supported ranges
var reader = new FdtReader(Plugin.DataManager.GetFile("common/font/axis_12.fdt")!.Data);
foreach (var c in reader.Glyphs)
builder.AddChar(c.Char);
// Common extras (Axis ingame glyphs, endonyms, enclosed alphanumerics)
// belong to the primary/Japanese ranges only. The trimmed CJK fallback
// skips them so it stays a pure Hangul/Simplified-Han remainder and
// does not re-merge the Default-block work the global font already did.
if (includeCommonExtras)
{
// Ingame supported ranges
var reader = new FdtReader(
Plugin.DataManager.GetFile("common/font/axis_12.fdt")!.Data
);
foreach (var c in reader.Glyphs)
builder.AddChar(c.Char);
// French
// Romanian
builder.AddText("Œœ");
builder.AddText("ĂăÂâÎîȘșȚț");
// French
// Romanian
builder.AddText("Œœ");
builder.AddText("ĂăÂâÎîȘșȚț");
// v1.5.3: language-dropdown endonyms. The dropdown renders
// with the currently active font range; without these glyphs
// a user on an English UI cannot read non-Latin language names
// before switching. Auto-activation in Settings.Apply then
// pulls in the full ExtraGlyphRange for the chosen locale.
builder.AddText(
"Català Čeština Dansk Deutsch Ελληνικά English Español Suomi"
+ " Français Magyar Italiano 日本語 한국어 Norsk bokmål Nederlands"
+ " Polski Português Brasil (Portugal) Română Русский Svenska"
+ " Türkçe Українська 简体中文 繁體中文"
);
// v1.5.3: language-dropdown endonyms. The dropdown renders
// with the currently active font range; without these glyphs
// a user on an English UI cannot read non-Latin language names
// before switching. Auto-activation in Settings.Apply then
// pulls in the full ExtraGlyphRange for the chosen locale.
builder.AddText(
"Català Čeština Dansk Deutsch Ελληνικά English Español Suomi"
+ " Français Magyar Italiano 日本語 한국어 Norsk bokmål Nederlands"
+ " Polski Português Brasil (Portugal) Română Русский Svenska"
+ " Türkçe Українська 简体中文 繁體中文"
);
// "Enclosed Alphanumerics" (partial) https://www.compart.com/en/unicode/block/U+2460
for (var i = 0x2460; i <= 0x24B5; i++)
builder.AddChar((char)i);
// "Enclosed Alphanumerics" (partial) https://www.compart.com/en/unicode/block/U+2460
for (var i = 0x2460; i <= 0x24B5; i++)
builder.AddChar((char)i);
builder.AddChar('⓪');
}
builder.AddChar('⓪');
return builder.BuildRangesToArray();
}
@@ -308,8 +491,17 @@ public sealed class FontManager : IDisposable
}
}
Ranges = BuildRange(customChars.Count > 0 ? customChars : null, ranges.ToArray());
JpRange = BuildRange(GlyphRangesJapanese.GlyphRanges);
Ranges = BuildRange(
customChars.Count > 0 ? customChars : null,
includeCommonExtras: true,
ranges.ToArray()
);
JpRange = BuildRange(GlyphRangesJapanese.GlyphRanges, includeCommonExtras: true);
// The fallback gets only the trimmed Hangul/Simplified-Han remainder.
// No Default block, no endonyms — those are already merged by the global and
// Japanese fonts, so re-merging them on the fallback was wasted atlas work.
CjkFallbackGlyphRange = BuildRange(CjkFallbackRange.Pairs, includeCommonExtras: false);
}
// Add font with fallback to NotoSansCjkRegular if unavailable
+18
View File
@@ -0,0 +1,18 @@
using HellionChat.Themes;
namespace HellionChat;
// Pure size resolution, split out of FontManager so it is unit-testable without
// building the font atlas. A typography override wins; null falls back to config.
internal static class FontSizeResolver
{
internal static float ResolveGlobalPt(
ThemeTypography? typography,
bool useHellionFont,
float fontSizeV2,
float globalSizePt
) => typography?.OverrideGlobalFontSizePt ?? (useHellionFont ? fontSizeV2 : globalSizePt);
internal static float ResolveSymbolsPt(ThemeTypography? typography, float symbolsSizePt) =>
typography?.OverrideSymbolsFontSizePt ?? symbolsSizePt;
}
+63 -69
View File
@@ -232,15 +232,13 @@ internal sealed unsafe class Chat : IDisposable
if (c != '\0' && !char.IsControl(c))
input = c.ToString();
try
// Seed the just-typed character into our input field and focus it, the
// same InputBar.AppendPending + Activate prefill path inventory item-links
// use. Prefill only, deliberately: no tab switch.
if (input != null)
{
Plugin.ChatLogWindow.Activated(
new ChatActivatedArgs(new ChannelSwitchInfo(null)) { Input = input }
);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in chat Activated event");
Plugin.InputBar.AppendPending(input);
Plugin.InputBar.Activate = true;
}
});
}
@@ -255,22 +253,12 @@ internal sealed unsafe class Chat : IDisposable
addIfNotPresent = add;
}
try
// Route the addIfNotPresent token into the InputBar so inventory
// right-click "Link item" reaches our input field instead of being lost.
if (addIfNotPresent != null && !Plugin.InputBar.PendingMessage.Contains(addIfNotPresent))
{
// Prevent duplicate calls
if (Plugin.ChatLogWindow.TellSpecial)
return ChatLogRefreshHook!.Original(log, eventId, value);
Plugin.ChatLogWindow.Activated(
new ChatActivatedArgs(new ChannelSwitchInfo(null))
{
AddIfNotPresent = addIfNotPresent,
}
);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in chat Activated event");
Plugin.InputBar.AppendPending(addIfNotPresent);
Plugin.InputBar.Activate = true;
}
return 1; // Prevent vanilla chat log from gaining focus
@@ -329,6 +317,30 @@ internal sealed unsafe class Chat : IDisposable
ReplyInSelectedChatModeHook!.Original(agent);
}
// Pure /tell-prefill command builder, shared by the two native SetTellTarget
// detours and the PayloadHandler Send-Tell payload. Empty/null world drops the
// @World suffix (matches the old IsNullOrEmpty guard); trailing space lets the
// user type straight after. internal static so the Build-Suite can pin it
// frame-free. TEST-MIRROR: ../../../Hellion Build test/GameFunctions/PrefillTellCommandTests.cs
internal static string BuildTellCommand(string name, string? world)
{
var command = $"/tell {name}";
if (!string.IsNullOrEmpty(world))
command += $"@{world}";
command += " ";
return command;
}
// Prefills + focuses our own input bar with a /tell command. The DI/Dalamud
// plumbing (Plugin.InputBar) lives here; the string assembly is BuildTellCommand.
// The in-foray TellSpecial routing (SetEurekaTellChannel) is NOT this helper's
// job — it stays at the call-site (v1.8.1 deferral).
private void PrefillTellInput(string name, string? world)
{
Plugin.InputBar.SetPendingMessage(BuildTellCommand(name, world));
Plugin.InputBar.Activate = true;
}
private bool SetContextTellTarget(
RaptureShellModule* a1,
Utf8String* playerName,
@@ -342,28 +354,14 @@ internal sealed unsafe class Chat : IDisposable
{
if (playerName != null)
{
try
{
var target = new TellTarget(
playerName->ToString(),
worldId,
contentId,
(TellReason)reason
);
Plugin.ChatLogWindow.Activated(
new ChatActivatedArgs(
new ChannelSwitchInfo(InputChannel.Tell, permanent: setChatType)
)
{
TellReason = (TellReason)reason,
TellTarget = target,
}
);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in chat Activated event");
}
// Right-click -> Send Tell: prefill our input the same way our own
// "Send Tell" payload menu does (PayloadHandler), then focus. Prefill
// only, deliberately: no tab switch, no ChatActivatedArgs revival.
// The game supplies worldName here, so no sheet lookup.
PrefillTellInput(
playerName->ToString(),
worldName != null ? worldName->ToString() : null
);
}
return SetChatLogTellTargetHook!.Original(
@@ -393,27 +391,13 @@ internal sealed unsafe class Chat : IDisposable
if (playerName != null)
{
try
{
var target = new TellTarget(
playerName->ToString(),
worldId,
contentId,
(TellReason)reason
);
Plugin.ChatLogWindow.Activated(
new ChatActivatedArgs(new ChannelSwitchInfo(InputChannel.Tell))
{
TellReason = (TellReason)reason,
TellTarget = target,
TellSpecial = Sheets.IsInForay(), // Handle Eureka/Bozja special
}
);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in chat Activated event");
}
// In-foray right-click -> Send Tell: same prefill path as the non-foray
// tell. The foray-specific TellSpecial channel routing stays deferred
// (v1.8.1, SetEurekaTellChannel) -- prefill only here as well.
PrefillTellInput(
playerName->ToString(),
worldName != null ? worldName->ToString() : null
);
}
ContextMenuTellInForayHook!.Original(
@@ -467,6 +451,17 @@ internal sealed unsafe class Chat : IDisposable
uint currentIndex,
RotateMode rotate,
Func<uint, bool> validFn
) => RotateLinkshellIndex(currentIndex, rotate, validFn);
// Pure index-stepper (Dalamud-free): wrap (8 + currentIndex + delta) % 8 and return the
// first index validFn accepts within 8 iterations, else null. Extracted so the
// modulo/termination logic is unit-testable with a synthetic predicate; the
// production caller binds validFn to InfoProxyLinkshell (in-game only).
// TEST-MIRROR: ../../../Hellion Build test/_Helpers/RotateLinkshellIndexTests.cs
internal static uint? RotateLinkshellIndex(
uint currentIndex,
RotateMode rotate,
Func<uint, bool> validFn
)
{
if (rotate == RotateMode.None)
@@ -570,9 +565,8 @@ internal sealed unsafe class Chat : IDisposable
if (!Plugin.CurrentTab.CurrentChannel.UseTempChannel)
Plugin.CurrentTab.CurrentChannel.UseTempChannel = true;
// Send tell via CommandInner later and let the game handle it
// Only works because we use the SetTellTargetInForay function to set all required information
Plugin.ChatLogWindow.TellSpecial = true;
// Send tell via CommandInner later and let the game handle it.
// TellSpecial gate is offline until the new chat layer reads it.
var utfName = Utf8String.FromString(name);
var utfWorld = Utf8String.FromString(worldName);
+173 -17
View File
@@ -7,6 +7,7 @@ using FFXIVClientStructs.FFXIV.Client.System.String;
using FFXIVClientStructs.FFXIV.Client.UI;
using HellionChat.Code;
using HellionChat.GameFunctions.Types;
using HellionChat.Ui.Windows;
using HellionChat.Util;
using Microsoft.Extensions.Logging;
using ModifierFlag = HellionChat.GameFunctions.Types.ModifierFlag;
@@ -504,33 +505,188 @@ internal unsafe class KeybindManager : IDisposable
if (!KeybindsToIntercept.TryGetValue(currentBest.Item2, out var info))
return;
// Resolve the surface this keybind acts on FIRST: a focused pop-out otherwise
// the main window. Channel-set/REPLY/prefill all write here so the action
// follows the input the user is typing in.
var (targetWindow, targetTab) = ResolveKeybindTarget();
// Surface + focus the resolved target ONCE, before routing. Main: ActivateChat
// re-surfaces it from a hide/closed state (the chat-activation entry point
// retired in v1.6.0). Pop-out: arm only its focus — NOT ActivateChat, which
// would yank the main window to front and un-hide it on every pop-out-targeted
// keybind: stay where the user types. Exactly one window arms focus per
// keybind, so the next frame has no SetKeyboardFocusHere race.
if (targetWindow is ChannelPopoutWindow)
targetWindow.RequestInputFocus();
else
Plugin.Instance.MainWindow?.ActivateChat();
// The routing tail makes native game calls (GetTellHistoryInfo, UIModule,
// RotateLinkshellHistory) on the framework tick — wrap it so one bad frame logs
// instead of throwing into Dalamud's update loop (v1.5.6 parity).
try
{
TellReason? reason = info.Channel == InputChannel.Tell ? TellReason.Reply : null;
Plugin.ChatLogWindow.Activated(new ChatActivatedArgs(info) { TellReason = reason });
if (info.Channel is { } channel && info.Rotate == RotateMode.None)
{
// Direct channel-switch binds (CMD_SAY/PARTY/numbered linkshells/…): switch
// the game channel AND mirror it onto the resolved tab so the input pill
// shows the real send target (pill-sync).
Plugin.Instance.Functions.Chat.SetChannel(channel);
// Only mirror onto the tab when the game actually accepted the switch — an
// empty linkshell slot leaves the game channel untouched, so the pill must
// stay put rather than show a target the game will not send to.
if (Chat.IsChannelOrExistingLinkshell(channel) && targetTab is { } directTab)
{
directTab.CurrentChannel.SetChannel(channel);
directTab.CurrentChannel.TellTarget = null;
directTab.CurrentChannel.ResetTempChannel();
}
}
else if (info.Channel is { } rotateChannel && info.Rotate != RotateMode.None)
{
// Rotation binds (REPLY / linkshell-cycle). Ported from v1.5.6's
// ChatLogWindow.Activated (1d3b429:240-334) without the ChatActivatedArgs
// indirection (gone in the rewrite). Writes onto the resolved surface's
// tab, not Plugin.CurrentTab.
if (targetTab is { } rotTab)
{
var targetChannel = (InputChannel?)rotateChannel;
// REPLY rotation: the reply target is ALWAYS temp (never permanent —
// a permanent reply would leak the partner onto the tab) and ALWAYS
// TellReason.Reply. info.Permanent does not gate this step; only the
// channel-set tail below honours the _ALWAYS binds' permanence.
if (rotateChannel == InputChannel.Tell)
{
var idx =
rotTab.CurrentChannel.TempChannel != InputChannel.Tell ? 0
: info.Rotate == RotateMode.Reverse ? -1
: 1;
var tellInfo = Plugin.Instance.Functions.Chat.GetTellHistoryInfo(idx);
if (tellInfo != null)
rotTab.CurrentChannel.TempTellTarget = new TellTarget(
tellInfo.Name,
tellInfo.World,
tellInfo.ContentId,
TellReason.Reply
);
}
else
{
// Cycling AWAY from Tell to a linkshell: drop any stale permanent
// tell target so a typed line cannot silently route to the old
// partner (v1.5.6 ChatLogWindow.cs:280, privacy guard).
rotTab.CurrentChannel.TellTarget = null;
}
// LS/CWLS cycle: permanent rotates the game's own history and reads the
// landed cycle index back; temp resolves the next valid linkshell index
// without touching game state. Both leave targetChannel null on failure
// (no valid linkshell in 8 iterations) so the tail below logs + skips.
if (rotateChannel is InputChannel.Linkshell1 or InputChannel.CrossLinkshell1)
{
var module = UIModule.Instance();
if (info.Permanent)
{
if (rotateChannel == InputChannel.Linkshell1)
{
Chat.RotateLinkshellHistory(info.Rotate);
targetChannel = rotateChannel + (uint)module->LinkshellCycle;
}
else
{
Chat.RotateCrossLinkshellHistory(info.Rotate);
targetChannel =
rotateChannel + (uint)module->CrossWorldLinkshellCycle;
}
}
else
{
targetChannel = Chat.ResolveTempInputChannel(
rotTab.CurrentChannel.TempChannel,
rotateChannel,
info.Rotate
);
}
}
// Shared channel-set tail (runs for Tell too: IsChannelOrExistingLinkshell
// is true for Tell and targetChannel stays Tell). Permanent => commit the
// game channel; temp => arm UseTempChannel/TempChannel only. This is the
// ONLY place info.Permanent decides temp vs permanent for the channel.
if (
targetChannel is null
|| !Chat.IsChannelOrExistingLinkshell(targetChannel.Value)
)
{
_logger.LogWarning(
"Rotation channel resolved to an invalid value '{Channel}', ignoring",
targetChannel
);
return;
}
if (info.Permanent)
{
// 1.5.6 parity (ChatLogWindow.SetChannel, 1d3b429:1476-1479):
// committing the game channel also pre-targets the game's native input.
// Forward the tab's reply target for Tell so the partner is armed
// game-side (ChangeChatChannel code 17); null for a linkshell —
// targetChannel is the FINAL resolved value (9..16/19..26 for LS, never
// 0=Tell), so a stale TempTellTarget can never flip an LS cycle to Tell.
var gameTarget =
targetChannel.Value == InputChannel.Tell
? rotTab.CurrentChannel.TempTellTarget
?? rotTab.CurrentChannel.TellTarget
: null;
Plugin.Instance.Functions.Chat.SetChannel(targetChannel.Value, gameTarget);
rotTab.CurrentChannel.SetChannel(targetChannel.Value);
}
else
{
rotTab.CurrentChannel.UseTempChannel = true;
rotTab.CurrentChannel.TempChannel = targetChannel.Value;
}
}
}
// Prefill text binds (CMD_COMMAND seeds "/"): the token always goes to the
// main InputBar (the focus contract does not expose pop-out buffers); a
// focused pop-out already received focus above, so only token routing matters
// here -- a documented scope limit.
if (info.Text is { } text)
Plugin.Instance.InputBar.SetPendingMessage(text);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in chat Activated event");
_logger.LogError(ex, "Keybind routing failed for channel {Channel}", info.Channel);
}
}
// v0.6.0 — central dispatch for ChatTabForward/Backward. If a pop-out
// window currently has its compact input focused, the keybind is
// forwarded into that pop-out's ChatInputBar so the user navigates
// tabs in the window they are typing in. Otherwise the main window
// handles it (= v0.5.x behavior).
// Resolve which chat surface a keybind action targets: the open pop-out whose
// input currently has focus, otherwise the main window. Both paths share it so a
// channel-switch/REPLY/prefill follows the surface the user is typing in. The
// returned tab is that surface's bound tab (pop-out: Bound; main: ActiveTab).
// Null tab => skip the tab-write (early-load window where no tab exists yet).
private (IFocusableChatWindow Window, Tab? Tab) ResolveKeybindTarget()
{
foreach (var popout in Plugin.Instance.ChannelPopoutPool.Instances)
{
if (popout.Bound is { } bound && popout.IsOpen && popout.HasFocusedInput)
return (popout, bound);
}
var main = Plugin.Instance.MainWindow;
return (main!, main?.ActiveTab);
}
// Tab-delta keybinds (ChatTabForward/Backward) stay main-window-only by design:
// a channel-bound pop-out has no tab list to cycle. The focus contract is
// consumed by the channel-set/REPLY/prefill tail, not here.
private void DispatchTabDelta(int delta)
{
foreach (var popout in Plugin.ChatLogWindow.ActivePopouts)
{
if (popout.HasFocusedInputBar && popout.InputBar != null)
{
popout.InputBar.HandleKeybindForward(delta);
return;
}
}
Plugin.ChatLogWindow.ChangeTabDelta(delta);
Plugin.Instance.MainWindow?.ChangeTabDelta(delta);
}
private static Keybind GetKeybind(string id)
+2 -2
View File
@@ -1,7 +1,7 @@
<Project Sdk="Dalamud.NET.Sdk/15.0.0">
<PropertyGroup>
<!-- Independent versioning; see yaml changelog for upstream Chat 2 base -->
<Version>1.5.6</Version>
<Version>2.0.2</Version>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- Use lock file to pin exact versions -->
@@ -13,7 +13,7 @@
<ItemGroup>
<!-- Closed ranges prevent surprise major bumps during lock file regeneration -->
<PackageReference Include="MessagePack" Version="[3.1.4, 4.0.0)" />
<PackageReference Include="MessagePack" Version="[3.1.7, 4.0.0)" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.8" />
<!-- v1.5.0 DI-container foundation; matches Lightless pin (Hosting 10.0.7) -->
<PackageReference
+52 -132
View File
@@ -27,7 +27,7 @@ icon_url: https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/raw/br
image_urls:
- https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/raw/branch/main/HellionChat/images/chatWindow.png
- https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/raw/branch/main/HellionChat/images/settingsOverview.png
- https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/raw/branch/main/HellionChat/images/themesPicker.png
- https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/raw/branch/main/HellionChat/images/firstRunWizard.png
tags:
- Social
- UI
@@ -35,6 +35,56 @@ tags:
- Replacement
- Privacy
changelog: |-
**v2.0.2 — Emotes out, placeholders fixed (2026-08-19)**
- **BetterTTV emote support is gone.** Its shared-emote endpoint went behind authentication, and that was where nearly all of them came from — what remained was a 65-entry global set, eleven of which are on the known-broken list, so 54 mostly static images from Twitch's early days. Exactly one was animated, and that one wanted 492 frames and 37 MB of video memory. The plugin now makes no outbound network calls at all. Messages stored with emotes still read fine; they show the code that was typed.
- **Five settings descriptions printed `{0}` instead of the plugin name.** All 25 languages were affected, English included — it just hid better there, since "Hide {0} during cutscenes" still scans as a sentence while German puts the placeholder first. A test now walks every resource string with a placeholder and fails if one reaches a widget unformatted.
- **New preview images.** The ones in the plugin installer were from 8 May and showed the interface as it looked before any of the window rebuilds.
---
**v2.0.1 — Hotfix (2026-08-19)**
A same-day follow-up to 2.0.0 with no user-facing changes. Install it if you picked up 2.0.0 in the first hour; there is nothing new to look at, it just carries a dependency update the 2.0.0 archive was built without.
- MessagePack raised from 3.1.4 to 3.1.7. It handles the payload serialisation behind the message database. The advisories are a recursion-depth limit in `Skip` and a fault in LZ4 decompression, both reachable only through crafted input — this plugin writes and reads its own bytes in a local file, so the practical exposure needs someone who already has write access to it. Lifted anyway, because it costs nothing.
- The release workflow publishes through the Gitea API directly. The 2.0.0 build succeeded and then failed to attach its own archive, which is why that release had to be completed by hand.
---
**v2.0.0 — Rebuilt, Repaired, Reset (2026-08-19)**
Nine development cycles in one release. Everything built as v1.6.0 through v1.15.0 ships here; those versions were never published on their own.
**This update resets your settings.** Nine cycles of rebuilding left saved values pointing at surfaces that no longer exist, and starting over is the only way to be sure every install is on the same defaults. **Your message history is untouched** — it lives in a separate database. Your old settings are kept next to the config file as `HellionChat.json.pre-2.0.0.bak`.
Fixed, and several of these lost data or hid it:
- Retroactive cleanup could never be applied at all. The preview took the database lock itself and that counted as a change, so every preview went stale the instant it finished and the apply button never appeared.
- Compacting the database ran against an open reader and failed, after which the plugin reported that nothing had been deleted — while everything had.
- Deleting messages left them in the search index, so search kept returning rows that were already gone.
- Pinned tell tabs came up empty for a whole session: the history query ran at plugin start, before any character is logged in, and never tried again.
- Export wrote invalid JSON where a setting value was involved, and a byte-order mark that strict parsers reject.
- A pop-out with its title bar switched on could not be closed, and a tell from a popped-out partner hijacked the main window's active tab.
- One third-party emote service started returning 403, and that response took all 65 working global emotes down with it on every start.
- The GDPR notice for the full-history profile had been translated into 25 languages and shown nowhere since May.
Changed, and one of these changes what gets stored:
- **The channel grid is now authoritative.** Until now the unknown-channel failsafe was applied to known channels too, so a channel you had unticked was still being written while that failsafe was on. If that was you, this release stores less than before. Nothing already in the database is touched.
- Every window is drawn by the plugin rather than by ImGui defaults, and they share one visual language: structure carried by typography, a surface on anything you can press, and colours measured against what sits behind them.
- Typography has named roles — sender, body and timestamp mean the same thing everywhere, timestamps sit in their own column, system messages are italic.
- Export, the tab editor, database maintenance and pinning had lost their entry points during the rebuild and are reachable again.
- Screenshot mode reached one of four surfaces that draw a tab name. It reaches all four now.
Removed: six settings that had a control and a saved value but no reader anywhere in the plugin; a per-tab regex filter the game's own blackword filter covers; and a wizard checkbox that was collected, reported as applied and never read.
New: an Emote tab in the default layout, local and server clocks in the status bar, a screenshot mode reachable from the input row, `/hellion wizard` to reopen the setup wizard, a style lab under `/hellion lab`, and 25 UI languages with the settings window and wizard fully covered.
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2). The two codebases have diverged far enough that they no longer line up.
---
**v1.5.6 — Settings Overhaul + Filter & Notification Polish (2026-05-23)**
- Settings window reorganised: ten tabs down to seven (General, Appearance, Chat, Window, Channels, Data & Privacy, About). Each tab now uses collapsible sections grouped by control type. Sections start collapsed every time you open a tab — less noise, easier to find what you need.
@@ -47,134 +97,4 @@ changelog: |-
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
---
**v1.5.5 — Upstream-Sync Tab-Features (2026-05-21)**
A backlog-sync cycle: inherited tab-feature items plus a new fox
banner image and custom notification sounds.
User-visible:
- Failed tells now raise a warning toast when a message you sent
could not be delivered (recipient offline, in an instance, or
blocking you). Toggle in Settings, Chat tab.
- Per-tab notification sound: each tab can play a sound when a
message arrives while you are looking at a different tab. Pick
one of the 16 game chat sounds or one of three bundled Hellion
sounds, with a preview button to hear it. Off by default,
respects the global sound toggle.
- The tab rename field in the right-click menu now focuses
itself when the menu opens and accepts up to 512 characters,
matching the settings-tab rename.
- A jump-to-latest button appears in the chat log header while
you are scrolled up from the live end.
- Map flags and item links can be inserted into the chat input
from its right-click menu.
- The Hellion Forge fox banner in the first-run wizard and the
Information tab is now a real image instead of ASCII art.
Schema bumped to v18 (additive fields only, no data migration).
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
---
**v1.5.4 — Polish and Motion (2026-05-20)**
A polish cycle: smoother theme switching, faster theme and tab
access, and subtle hover motion. Three P3 items plus an
accessibility toggle.
User-visible:
- Theme switches now crossfade smoothly over ~300 ms across every
Hellion-rendered surface — sidebar, title, buttons, tabs,
scrollbar, separators. The window background snaps deliberately
so the per-window opacity override from Dalamud's pinning menu
stays untouched.
- New header quick-picker: a palette button left of the cog opens
a compact popup with two sections — every built-in and custom
theme, and every tab. The active entry carries a check glyph;
clicking another switches without closing the popup.
- Sidebar icons ease their opacity on hover, and card-mode message
borders highlight per tab while the cursor is over their rows.
Framerate-independent, so a stalled Wine frame cannot overshoot
the animation.
- New "Reduce motion" toggle in Theme & Layout disables the
crossfade, the hover animations and the unread-tab pulse for
users who prefer a static UI.
Under the hood:
- Two pure-helper lerp paths (ThemeAbgrCacheLerp, FrameLerp) with
xUnit coverage in the Build Suite, plus a ColourUtil.ApplyAlpha
alpha modulator. Two new /xlperf self-test steps pin the
crossfade and quick-picker contracts.
No schema bump, no migration. Migration v17 stays.
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
---
**v1.5.3 — Localisation Wave + Bundled-Font Overhaul (2026-05-19)**
Multi-language pass plus a long-standing first-frame HITCH lands
as a side effect of a font-stack rewrite.
User-visible:
- 24 selectable UI languages (was 2). Catalan, Czech, Danish,
Dutch, English, Finnish, French, German, Greek, Hungarian,
Italian, Japanese, Korean, Norsk bokmål, Polish, Portuguese
(BR + PT), Romanian, Russian, Spanish, Swedish, Turkish,
Ukrainian, Simplified + Traditional Chinese. Sorted by endonym,
"None" pinned first. Non-native locales are AI-assisted and
flagged for native-speaker review via the Forge Discord.
- Bundled Inter Light replaces Exo 2 (SIL OFL 1.1, 343 KB). The
Inter font ships Latin Extended-A/B, Greek polytonic and
Cyrillic Supplement coverage; NotoSansCjkRegular joins as a
third merge layer for Hangul and Simplified-Han glyphs the
FFXIV Japanese game font does not ship.
- First-frame HITCH dropped from ~74 ms (v1.5.2 baseline that
held since v1.4.x) to a median of ~20 ms (5-reload sample
17.9-23.6 ms, Linux/Wine). The bundled-font path silently
fell back to the FFXIV Axis font for the entire v1.5.x series
because of an early-return in the draw loop. The fix that
routes RegularFont through draw also lands the defer-pattern
win the v1.5.1 cycle was reaching for.
- ExtraGlyphRanges auto-activates on language change. Korean,
ChineseFull and the two new flags (LatinExtended, Greek) toggle
on without a manual visit to Fonts and Colours.
- New WarningText under the language dropdown notes FFXIV's
chat input only fully supports EN/DE/FR/JA character sets.
Other languages render in HellionChat but may garble when
typed into in-game chat.
Under the hood:
- Three-layer font stack: Inter Light primary, FFXIV
JapaneseFont merge 1 for kana/kanji style, NotoSansCjkRegular
merge 2 for everything else CJK.
- LanguageOverride enum gains ten locales plus three previously
commented out (Italian, Korean, Norwegian as `nb`). New
values append to the enum so existing config integers stay
stable across update.
- Crowdin gap closed: four post-sync ChatTwo keys backfilled
into 13 legacy locales with per-key AI markers.
- Plugin.LoadAsync runs a one-shot migration that ORs in the
matching ExtraGlyphRanges flag for users already on a
non-default language. Settings.Apply auto-activates on
change going forward.
- Em-dash sweep across the EN source and 18 translations to the
house style. Russian and Ukrainian keep the typographic norm.
Migration v17 stays. UseHellionFont users transition from Exo 2
to Inter Light transparently on first reload.
Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
---
Full history: https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases
Earlier history: https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases
@@ -1,7 +1,11 @@
using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Plugin;
using HellionChat.Integrations;
using HellionChat.Ipc;
using HellionChat.Themes;
using HellionChat.Ui;
using HellionChat.Ui.Components;
using HellionChat.Ui.Windows;
using Microsoft.Extensions.Hosting;
namespace HellionChat.Infrastructure.Hosting;
@@ -12,16 +16,26 @@ namespace HellionChat.Infrastructure.Hosting;
// at Build, which runs the service ctor (IPC subscribe etc.) right then
// instead of lazily on first GetRequiredService.
internal sealed class ThemeRegistryInitHostedService(ThemeRegistry registry) : IHostedService
internal sealed class ThemeRegistryInitHostedService(
ThemeRegistry registry,
FontManager fontManager
) : IHostedService
{
public Task StartAsync(CancellationToken cancellationToken)
public async Task StartAsync(CancellationToken cancellationToken)
{
// Materialise the lazy AllCustom enumerable so the slug lookup hits a
// warm cache; otherwise the first Switch falls through to the built-in
// default when Config.Theme points at a custom slug.
foreach (var _ in registry.AllCustom()) { }
registry.SwitchSilent(Plugin.Config.Theme);
return Task.CompletedTask;
// B4b-3: point font sizes at the active theme's typography, wire future
// theme switches to the atlas rebuild, and apply the boot theme's override.
fontManager.SetTypographySource(() => registry.Active.Typography);
registry.SetActiveChangedCallback(() => fontManager.RebuildDelegateFontsIfChanged());
await Plugin.Framework.RunOnFrameworkThread(() =>
fontManager.RebuildDelegateFontsIfChanged()
);
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
@@ -87,6 +101,18 @@ internal sealed class AutoTellTabsServiceInitHostedService(AutoTellTabsService s
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
internal sealed class TellRouterServiceInitHostedService(Services.TellRouterService service)
: IHostedService
{
public Task StartAsync(CancellationToken cancellationToken)
{
service.Initialize();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
// Eager-resolve trigger: resolving FailedTellNotifier in this adapter's ctor
// enables its game hook during host startup. StartAsync itself is a no-op.
internal sealed class FailedTellNotifierInitHostedService(FailedTellNotifier notifier)
@@ -101,3 +127,82 @@ internal sealed class FailedTellNotifierInitHostedService(FailedTellNotifier not
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
internal sealed class PayloadHandlerInitHostedService(
PayloadHandler payloadHandler,
MessageList messageList
) : IHostedService
{
public async Task StartAsync(CancellationToken cancellationToken)
{
// Cycle resolution: both singletons exist by the time HostedServices
// run, so this is the first safe point to wire the setter.
messageList.AttachPayloadHandler(payloadHandler);
// IAddonLifecycle thread-affinity is not explicitly documented; wrap is
// defensive insurance — mirrors the window-registration RunOnFrameworkThread
// pattern established in PluginLifecycle.cs.
await Plugin.Framework.RunOnFrameworkThread(() =>
{
Plugin.AddonLifecycle.RegisterListener(
AddonEvent.PostUpdate,
"ItemDetail",
payloadHandler.MoveTooltip
);
Plugin.AddonLifecycle.RegisterListener(
AddonEvent.PostUpdate,
"ActionDetail",
payloadHandler.MoveTooltip
);
});
}
public async Task StopAsync(CancellationToken cancellationToken)
{
await Plugin.Framework.RunOnFrameworkThread(() =>
{
// Single call using the params-overload removes the delegate from all addons it was registered for (ItemDetail + ActionDetail both cleaned in one shot).
Plugin.AddonLifecycle.UnregisterListener(payloadHandler.MoveTooltip);
});
}
}
// Wires MainWindow into CommandHelpWindow post-container-build. CommandHelpWindow
// cannot take MainWindow as a ctor-param because that would close the cycle
// InputBar -> CommandHelpWindow -> MainWindow -> InputBar (MS.DI does not catch
// it through FactoryCallSite registrations and the resolve recurses silently).
// Both singletons exist by host.StartAsync time, so this is the first safe point
// to wire the setter — same setter-injection pattern as MessageList.AttachPayloadHandler.
internal sealed class CommandHelpWindowInitHostedService(
CommandHelpWindow commandHelpWindow,
MainWindow mainWindow
) : IHostedService
{
public Task StartAsync(CancellationToken cancellationToken)
{
commandHelpWindow.AttachMainWindow(mainWindow);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
// Attaches the singleton PayloadHandler to every pre-allocated pop-out
// window's MessageList post-container-build. Pool/window cannot take the
// PayloadHandler via ctor (that would close the silent FactoryCallSite cycle —
// same setter-injection reason as MessageList.AttachPayloadHandler / CommandHelpWindow.
// AttachMainWindow). Both singletons exist by host.StartAsync time.
internal sealed class ChannelPopoutInitHostedService(
ChannelPopoutPool pool,
PayloadHandler payloadHandler
) : IHostedService
{
public Task StartAsync(CancellationToken cancellationToken)
{
foreach (var window in pool.Instances)
window.AttachPayloadHandler(payloadHandler);
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
@@ -195,4 +195,23 @@ internal sealed class HonorificService : IDisposable
return false;
return true;
}
// Test seam: the three status fields are private-set and IPC-driven, which a
// headless /xlperf run can't reach (Honorific is usually absent in tests).
// Callers MUST snapshot the prior values and restore them in CleanUp, and
// MUST drive Set -> Draw -> Assert within ONE synchronous RunStep (never
// Waiting between Set and Assert) — a between-frame OnReady/OnTitleChanged
// would otherwise clobber this state and a CleanUp restore can't un-corrupt a
// mid-flight assertion. (A FontsReady precondition gate returning Waiting
// BEFORE the snapshot/Set is fine — nothing is mutated yet.)
internal void TestOnly_SetState(
bool isAvailable,
(uint Major, uint Minor)? detectedApiVersion,
HonorificTitleData? title
)
{
IsAvailable = isAvailable;
DetectedApiVersion = detectedApiVersion;
CurrentTitle = title;
}
}
@@ -0,0 +1,29 @@
namespace HellionChat.Integrations;
internal enum HonorificStatusKind
{
NotInstalled,
Incompatible,
Detected,
}
internal static class HonorificStatus
{
// Mirrors the 1.5.6 three-state discriminator (1d3b429:About.cs:171/183/196):
// it keys on IsAvailable + the *nullability* of DetectedApiVersion, never a
// recomputed major check. IsAvailable already encodes the compatibility
// result HonorificService set during the initial pull. Null-safe: an
// (isAvailable=true, detectedApiVersion=null) state a test seam can produce
// resolves to NotInstalled rather than dereferencing null.
internal static HonorificStatusKind Resolve(
bool isAvailable,
(uint Major, uint Minor)? detectedApiVersion
)
{
if (isAvailable && detectedApiVersion is not null)
return HonorificStatusKind.Detected;
if (detectedApiVersion is not null)
return HonorificStatusKind.Incompatible;
return HonorificStatusKind.NotInstalled;
}
}
@@ -5,11 +5,10 @@ namespace HellionChat.Integrations;
// Local DTO mirroring Honorific's TitleData — no hard reference to Honorific.dll
// so HellionChat loads cleanly when Honorific is absent.
//
// Only Glow is rendered. Color3, GradientColourSet and GradientAnimationStyle
// are parsed but unused — the animated gradient lives entirely inside Honorific
// and is not exposed over IPC, so reproducing it here would mean shipping our
// own copy of Honorific's colour palette. The fields stay in the DTO so the
// JSON roundtrip remains lossless.
// Color is rendered in the header title slot (HonorificHeader). Glow, Color3,
// GradientColourSet and GradientAnimationStyle are parsed but not rendered —
// the animated gradient lives inside Honorific and is not exposed over IPC.
// The fields stay in the DTO so the JSON roundtrip remains lossless.
internal sealed record HonorificTitleData(
string? Title,
bool IsPrefix,
+1 -1
View File
@@ -31,7 +31,7 @@ public sealed class ExtraChat : IDisposable
// volatile: IPC callbacks fire on a Dalamud thread while ImGui reads these.
// Reference assignment is atomic on x64, but the barrier ensures visibility
// across threads (especially Mono/Wine). See AUDIT-2026-05-05 [SEC-01].
// across threads (especially Mono/Wine). Raised in the 2026-05-05 audit.
private volatile Dictionary<string, uint> ChannelCommandColoursInternal = new();
internal IReadOnlyDictionary<string, uint> ChannelCommandColours =>
ChannelCommandColoursInternal;
+23 -12
View File
@@ -20,7 +20,7 @@ internal sealed class TypingIpc : IDisposable
private ICallGateProvider<ChatInputState> StateQueryGate { get; }
private ICallGateProvider<ChatInputState, object?> StateChangedGate { get; }
// v1.4.9 R4: ChatTwo IPC compatibility mirror. Some third-party plugins
// v1.4.9: ChatTwo IPC compatibility mirror. Some third-party plugins
// have a no-fork policy and subscribe only to ChatTwo.*-prefixed IPC
// gates. HellionChat replaces ChatTwo (conflict detection prevents
// parallel loading), so mirroring the ChatTwo provider slots lets those
@@ -34,11 +34,13 @@ internal sealed class TypingIpc : IDisposable
private ChatInputState LastState;
private bool HasState;
private readonly Ui.Components.InputBar _inputBar;
private readonly ILogger<TypingIpc> _logger;
internal TypingIpc(Plugin plugin, ILogger<TypingIpc> logger)
internal TypingIpc(Plugin plugin, Ui.Components.InputBar inputBar, ILogger<TypingIpc> logger)
{
Plugin = plugin;
_inputBar = inputBar;
_logger = logger;
StateQueryGate = Plugin.Interface.GetIpcProvider<ChatInputState>(
@@ -48,7 +50,7 @@ internal sealed class TypingIpc : IDisposable
"HellionChat.ChatInputStateChanged"
);
// v1.4.9 R4: ChatTwo-prefixed compatibility slots (see class-level comment).
// v1.4.9: ChatTwo-prefixed compatibility slots (see class-level comment).
ChatTwoStateQueryGate = Plugin.Interface.GetIpcProvider<ChatInputState>(
"ChatTwo.GetChatInputState"
);
@@ -62,25 +64,34 @@ internal sealed class TypingIpc : IDisposable
private ChatInputState BuildState()
{
var log = Plugin.ChatLogWindow;
var usedChannel = Plugin.CurrentTab.CurrentChannel;
var inputChannel = usedChannel.UseTempChannel
? usedChannel.TempChannel
: usedChannel.Channel;
var channelType = inputChannel.ToChatType();
// MainWindow is Phase-1-resolved and never reassigned;
// the `?.` is defense-in-depth for pre-Phase-1 IPC-pulls.
var mainWindowOpen = Plugin.MainWindow?.IsOpen ?? false;
// Stale-state guard: InputBar's focus and pending-buffer fields are
// only written by DrawInputField. Closing MainWindow freezes them, so
// gate all four state fields on mainWindowOpen.
var inputFocused = mainWindowOpen && _inputBar.IsFocused;
var hasText = mainWindowOpen && _inputBar.PendingLength > 0;
var textLength = mainWindowOpen ? _inputBar.PendingLength : 0;
return (
InputVisible: !log.IsHidden,
log.InputFocused,
HasText: log.Chat.Length > 0,
IsTyping: log is { InputFocused: true, Chat.Length: > 0 },
TextLength: log.Chat.Length,
InputVisible: mainWindowOpen,
InputFocused: inputFocused,
HasText: hasText,
IsTyping: hasText,
TextLength: textLength,
ChannelType: channelType
);
}
private ChatInputState GetState() => BuildState();
internal ChatInputState GetState() => BuildState();
internal void Update()
{
@@ -91,7 +102,7 @@ internal sealed class TypingIpc : IDisposable
HasState = true;
LastState = state;
StateChangedGate.SendMessage(state);
// v1.4.9 R4: mirror on ChatTwo-prefixed slot for no-fork-policy plugins.
// v1.4.9: mirror on ChatTwo-prefixed slot for no-fork-policy plugins.
ChatTwoStateChangedGate.SendMessage(state);
}
+3 -3
View File
@@ -22,7 +22,7 @@ internal sealed class IpcManager : IDisposable
object?
> InvokeGate { get; }
// v1.4.9 R4: ChatTwo IPC compatibility mirror. Third-party plugins with
// v1.4.9: ChatTwo IPC compatibility mirror. Third-party plugins with
// a no-fork policy (e.g. Artisan, AllaganTools) only subscribe to the
// ChatTwo.*-prefixed context-menu integration gates. Mirroring all four
// provider slots under the ChatTwo namespace lets those plugins keep
@@ -65,7 +65,7 @@ internal sealed class IpcManager : IDisposable
object?
>("HellionChat.Invoke");
// v1.4.9 R4: ChatTwo-prefixed mirrors of the four context-menu slots
// v1.4.9: ChatTwo-prefixed mirrors of the four context-menu slots
// above. Share the same Register/Unregister backing methods so a
// plugin that subscribes via either namespace lands in the same
// Registered list. SendMessage on Invoke fans out to both gates.
@@ -103,7 +103,7 @@ internal sealed class IpcManager : IDisposable
)
{
InvokeGate.SendMessage(id, sender, contentId, payload, senderString, content);
// v1.4.9 R4: fan out the same event to plugins listening on ChatTwo.Invoke.
// v1.4.9: fan out the same event to plugins listening on ChatTwo.Invoke.
ChatTwoInvokeGate.SendMessage(id, sender, contentId, payload, senderString, content);
}
-21
View File
@@ -175,8 +175,6 @@ public partial class Message
}
var nextIsAutoTranslate = false;
var checkForEmotes =
(Code.IsPlayerMessage() || extraChatChannel != Guid.Empty) && Plugin.Config.ShowEmotes;
foreach (var chunk in oldChunks)
{
// Use as is if it's not a text chunk, it already has a payload, or is auto translate
@@ -207,25 +205,6 @@ public partial class Message
var wordUsed = false;
var tokenUsed = false;
if (
checkForEmotes
&& EmoteCache.Exists(word)
&& !Plugin.Config.BlockedEmotes.Contains(word)
)
{
// Add the previous sentence before adding the emote
AddChunkWithMessage(text.NewWithStyle(chunk, sentenceBuilder.ToString()));
AddChunkWithMessage(
new TextChunk(chunk.Source, EmotePayload.ResolveEmote(word), word)
{
FallbackColour = text.FallbackColour,
}
);
wordUsed = true;
sentenceBuilder.Clear();
}
if (token.TokenType == Tokenizer.TokenType.UrlString)
{
// Add the previous sentence before adding the url
+138 -39
View File
@@ -163,8 +163,15 @@ internal class MessageManager : IAsyncDisposable
internal void ClearAllTabs()
{
// Snapshot the tab LIST under the shared lock so the worker-thread
// add/remove can't tear the enumeration; tab.Clear() then runs lock-free
// (each tab's Messages has its own SemaphoreSlim — lock order: list outer).
List<Tab> tabsSnapshot;
lock (Plugin.TabsListLock)
tabsSnapshot = Plugin.Config.Tabs.ToList();
// TempTabs are session-only (not persisted); exclude them to preserve Tell history
foreach (var tab in Plugin.Config.Tabs.Where(t => !t.IsTempTab))
foreach (var tab in tabsSnapshot.Where(t => !t.IsTempTab))
tab.Clear();
}
@@ -176,18 +183,19 @@ internal class MessageManager : IAsyncDisposable
using var messages = Store.GetMostRecentMessages(CurrentContentId, since);
// TempTabs are excluded; they maintain live state from AutoTellTabsService
var pendingTabs = Plugin
.Config.Tabs.Where(t => !t.IsTempTab)
.Select(tab => (tab, new List<Message>()))
.ToList();
foreach (var message in messages)
foreach (var (_, pendingMessages) in pendingTabs.Where(ptab => ptab.Item1.Matches(message)))
pendingMessages.Add(message);
// TempTabs excluded (live state from AutoTellTabsService). Bucket via the
// pure MapMessagesToTabs so the assignment stays testable outside Dalamud.
// Snapshot under the shared lock (list copy only — short critical
// section). The Store query above and the AddSortPrune writes below stay
// OUTSIDE the lock (lock order: list outer, MessageList inner).
List<Tab> nonTempTabs;
lock (Plugin.TabsListLock)
nonTempTabs = Plugin.Config.Tabs.Where(t => !t.IsTempTab).ToList();
var buckets = MapMessagesToTabs(nonTempTabs, messages);
// Apply messages to chat log all at once.
foreach (var (tab, pendingMessages) in pendingTabs)
tab.Messages.AddSortPrune(pendingMessages, MessageDisplayLimit);
foreach (var tab in nonTempTabs)
tab.Messages.AddSortPrune(buckets[tab], MessageDisplayLimit);
if (!messages.DidError)
return;
@@ -206,6 +214,26 @@ internal class MessageManager : IAsyncDisposable
}
}
// Pure message->tab bucketing for the refilter. Dalamud-free + static so the
// assignment can be unit-pinned in the build suite; the live caller owns the
// Store query, the snapshot and the SemaphoreSlim writes.
internal static Dictionary<Tab, List<Message>> MapMessagesToTabs(
IReadOnlyList<Tab> tabs,
IEnumerable<Message> messages
)
{
var buckets = new Dictionary<Tab, List<Message>>(tabs.Count);
foreach (var tab in tabs)
buckets[tab] = new List<Message>();
foreach (var message in messages)
foreach (var tab in tabs)
if (tab.Matches(message))
buckets[tab].Add(message);
return buckets;
}
internal void FilterAllTabsAsync()
{
Task.Run(() =>
@@ -220,9 +248,8 @@ internal class MessageManager : IAsyncDisposable
_logger.LogError(ex, "Error in FilterAllTabs");
}
// v1.4.9 R3 profiling: Information so the xllog tail surfaces this
// without a Debug filter. Belt-and-suspenders for future plugin-load
// regressions; remains in place after Sub-Task 3.4 Befund.
// Information, not Debug, so the xllog tail surfaces this without a
// filter. Kept as a guard against future plugin-load regressions.
_logger.LogInformation($"FilterAllTabs took {stopwatch.ElapsedMilliseconds}ms");
});
}
@@ -331,34 +358,46 @@ internal class MessageManager : IAsyncDisposable
if (Plugin.Config.DatabaseBattleMessages || !message.Code.IsBattle())
Store.UpsertMessage(message);
var currentMatches = Plugin.CurrentTab.Matches(message);
uint? notificationSound = null;
foreach (var tab in Plugin.Config.Tabs)
// Snapshot the list, not just the active tab. This loop runs on the worker
// thread while SaveConfig's strip and the auto-tell spawn mutate Config.Tabs
// under TabsListLock — enumerating it live throws "collection was modified",
// and the catch in ProcessPendingMessages swallows that, silently dropping
// the whole message: no tab entry, no sound, no MessageProcessed.
List<Tab> tabsSnapshot;
lock (Plugin.TabsListLock)
tabsSnapshot = Plugin.Config.Tabs.ToList();
// Snapshot the active tab and whether it shows this message ONCE, so the
// whole loop sees a consistent value (the getter is a cross-thread read of
// MainWindow.ActiveTab).
var currentTab = Plugin.CurrentTab;
var currentTabMatches = currentTab.Matches(message);
foreach (var tab in tabsSnapshot)
{
var unread = !(
tab.UnreadMode == UnreadMode.Unseen && Plugin.CurrentTab != tab && currentMatches
);
if (tab.Matches(message))
{
tab.AddMessage(message, unread);
tab.AddMessage(message, ShouldCountUnread(tab, currentTab, currentTabMatches));
}
// Per-tab notification sound. Fire once for the first inactive
// tab that wants it, keeping a message matching several
// background tabs from stacking sounds.
// TEST-MIRROR: ../_Helpers/TabSoundDecision.cs
if (
notificationSound is null
&& TabSoundDecision.ShouldPlay(
Plugin.CurrentTab == tab,
tab.EnableNotificationSound,
Plugin.Config.PlaySounds
)
)
{
notificationSound = tab.NotificationSoundId;
}
}
// Deliberate O(2n): the sound pick re-walks the tab list so the selection
// stays pure and SelfTest-able; AddMessage above and playback below keep
// the side effects.
var notificationSound = SelectNotificationSound(
tabsSnapshot,
currentTab,
message,
Plugin.Config.PlaySounds,
out var soundSource
);
// The snapshot can outlive a tab (eviction, logout). Playing its sound would
// be an audible artefact for a tab that is already gone, so re-check first.
if (notificationSound is not null && soundSource is not null)
{
bool sourceStillPresent;
lock (Plugin.TabsListLock)
sourceStillPresent = Plugin.Config.Tabs.Contains(soundSource);
if (!sourceStillPresent)
notificationSound = null;
}
if (notificationSound is { } soundId)
@@ -388,6 +427,66 @@ internal class MessageManager : IAsyncDisposable
MessageProcessed?.Invoke(message);
}
// Pure: picks the sound id for the first inactive tab that wants one, or null.
// No AddMessage, no store write — those stay in the ProcessMessage loop so this
// is exercisable from the SelfTest without polluting tab state. The "first
// match wins" semantics live here via the running 'picked is null' guard,
// keeping a message matching several background tabs from stacking sounds.
// TEST-MIRROR: ../_Helpers/TabSoundDecision.cs
// Unseen ("count only what you haven't seen") suppresses unread on an inactive
// tab when the active tab ALSO shows this message — you already saw it in the
// tab you're looking at (1.5.6 / upstream ChatTwo behavior). The "active tab"
// used to be pinned to Tabs[0], so this fired against the wrong one until
// CurrentTab was recoupled to the real active tab, and currentTabMatches is
// now measured against the tab you see. All -> always counts; None ->
// counts here and is gated out at the display layer. Pure + SelfTest-able.
internal static bool ShouldCountUnread(Tab tab, Tab currentTab, bool currentTabMatches) =>
!(
tab.UnreadMode == UnreadMode.Unseen
&& !ReferenceEquals(currentTab, tab)
&& currentTabMatches
);
// Reports the tab the sound came from, so the caller can drop it if that tab
// disappeared between snapshot and playback.
internal static uint? SelectNotificationSound(
IEnumerable<Tab> tabs,
Tab currentTab,
Message probe,
bool playSounds,
out Tab? source
)
{
uint? picked = null;
source = null;
foreach (var tab in tabs)
{
if (!tab.Matches(probe))
continue;
if (
picked is null
&& TabSoundDecision.ShouldPlay(
currentTab == tab,
tab.EnableNotificationSound,
playSounds
)
)
{
picked = tab.NotificationSoundId;
source = tab;
}
}
return picked;
}
// SelfTest hook — same name discipline as InputBar.TestBuildOutgoingForSelfTest.
internal static uint? TestSelectNotificationSoundForSelfTest(
IEnumerable<Tab> tabs,
Tab currentTab,
Message probe,
bool playSounds
) => SelectNotificationSound(tabs, currentTab, probe, playSounds, out _);
internal class NameFormatting
{
internal string Before { get; private set; } = string.Empty;
+205 -57
View File
@@ -90,6 +90,8 @@ public class PayloadMessagePackFormatter : IMessagePackFormatter<Payload?>
return new PartyFinderPayload(reader.ReadUInt32());
case PayloadMessagePackType.Uri:
return new UriPayload(new Uri(reader.ReadString() ?? ""));
// Read-only since 2.0.2: nothing writes this any more, but rows
// stored before then carry it and must keep deserialising.
case PayloadMessagePackType.Emote:
return EmotePayload.ResolveEmote(reader.ReadString() ?? "");
case PayloadMessagePackType.Other:
@@ -245,7 +247,7 @@ internal class MessageStore : IDisposable
private SqliteConnection Connect()
{
// v1.4.9 R3 profiling: trace cost of SQLite open + pragma-apply. Paired
// v1.4.9 profiling: trace cost of SQLite open + pragma-apply. Paired
// with the Migrate-Stopwatch below — Connect alone is the cheap half
// (Open + a handful of PRAGMAs); the expensive half typically lives in
// Migrate, especially on a large DB after a schema bump.
@@ -260,7 +262,7 @@ internal class MessageStore : IDisposable
private void Migrate()
{
// v1.4.9 R3 profiling: trace cost of the schema-migration chain. On a
// v1.4.9 profiling: trace cost of the schema-migration chain. On a
// large DB after a fresh schema bump this is the dominant SQLite cost
// at plugin-load, not Connect.
var migrateSw = System.Diagnostics.Stopwatch.StartNew();
@@ -279,18 +281,25 @@ internal class MessageStore : IDisposable
migrationsToDo.Add(Migrate2);
migrationsToDo.Add(Migrate3);
migrationsToDo.Add(Migrate4);
migrationsToDo.Add(Migrate5);
break;
case 1:
migrationsToDo.Add(Migrate2);
migrationsToDo.Add(Migrate3);
migrationsToDo.Add(Migrate4);
migrationsToDo.Add(Migrate5);
break;
case 2:
migrationsToDo.Add(Migrate3);
migrationsToDo.Add(Migrate4);
migrationsToDo.Add(Migrate5);
break;
case 3:
migrationsToDo.Add(Migrate4);
migrationsToDo.Add(Migrate5);
break;
case 4:
migrationsToDo.Add(Migrate5);
break;
}
@@ -430,6 +439,23 @@ internal class MessageStore : IDisposable
SetMigrationVersion(4);
}
private void Migrate5()
{
_logger.LogInformation("Running migration 5: Add (Receiver, Date) index for tell history");
// GetTellHistoryWithSender filters on Receiver and orders by Date DESC.
// Without a matching index SQLite sorts the whole receiver history into a
// temp b-tree before returning row one, which defeats the early break in
// the caller. (Receiver, ChatType, Date) does NOT help: the ChatType IN
// filter sits between the equality prefix and the sort column.
using var cmd = Connection.CreateCommand();
cmd.CommandText =
"CREATE INDEX IF NOT EXISTS idx_messages_receiver_date ON messages (Receiver, Date);";
cmd.ExecuteNonQuery();
SetMigrationVersion(5);
}
private void SetMigrationVersion(int version)
{
_logger.LogInformation($"Setting version {version}");
@@ -440,35 +466,60 @@ internal class MessageStore : IDisposable
cmd.ExecuteNonQuery();
}
// Drops the full-text index and marks it for a rebuild.
//
// messages_fts stores sender_text and content_text in the clear, and no
// delete path touched it: ClearMessages, CleanupRetainOnly and the retention
// sweep all removed rows from `messages` only. The plain text of every
// "deleted" message stayed on disk.
//
// Worse, it was self-sealing. InitFtsReadyCache treats a non-empty index as
// ready, so after a wipe the index stayed full, the readiness flag stayed
// true, and the rebuild that would have cleared it never ran again.
//
// Wiping rather than deleting matched rows: message_guid is stored as a GUID
// string while messages.Id is a BLOB, so the two cannot be joined in SQL.
// The index is derived data and rebuilds from the surviving rows on the next
// start, which is the cheap and provably complete option.
//
// Caller must already hold _readLock.
private void InvalidateFtsIndex()
{
Connection.Execute("DELETE FROM messages_fts;");
_ftsReady = false;
}
internal void ClearMessages()
{
lock (_readLock)
{
Connection.Execute("DELETE FROM messages;");
PerformMaintenance();
InvalidateFtsIndex();
TryPerformMaintenance();
}
}
// Returns a (ChatType, count) snapshot over non-deleted messages.
// Used by the Privacy tab to preview retroactive cleanup impact.
internal Dictionary<int, long> GetMessageCountsByChatType()
//
// Caller-owned connection, same reasoning as StreamForExport: this is a
// GROUP BY over every row, and holding _readLock for it would stall
// UpsertMessage on the framework thread for as long as the scan takes.
internal Dictionary<int, long> GetMessageCountsByChatType(SqliteConnection conn)
{
lock (_readLock)
var result = new Dictionary<int, long>();
using var cmd = conn.CreateCommand();
cmd.CommandText =
"SELECT ChatType, COUNT(*) FROM messages WHERE deleted = false GROUP BY ChatType;";
cmd.CommandTimeout = 120;
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
var result = new Dictionary<int, long>();
using var cmd = Connection.CreateCommand();
cmd.CommandText =
"SELECT ChatType, COUNT(*) FROM messages WHERE deleted = false GROUP BY ChatType;";
cmd.CommandTimeout = 120;
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
var chatType = reader.GetInt32(0);
var count = reader.GetInt64(1);
result[chatType] = count;
}
return result;
var chatType = reader.GetInt32(0);
var count = reader.GetInt64(1);
result[chatType] = count;
}
return result;
}
// Deletes messages older than the per-channel retention window, with a global
@@ -505,6 +556,12 @@ internal class MessageStore : IDisposable
var index = 0;
foreach (var (type, days) in chatTypeDaysMap)
{
// Careful: 0 here is NOT the "keep forever" it means for
// defaultDays below. A per-channel 0 puts the cutoff at now
// and deletes the channel's entire history. No profile ships
// a 0 and no UI can set one, which is why this is a comment
// and not a guard -- but any editor added later has to
// reconcile the two meanings before it exposes the value.
var cutoff = nowMs - days * 86400000L;
var typeParam = $"$type{index}";
var cutoffParam = $"$cutoff{index}";
@@ -538,7 +595,11 @@ internal class MessageStore : IDisposable
}
if (deleted > 0)
PerformMaintenance();
{
InvalidateFtsIndex();
TryPerformMaintenance();
}
return deleted;
}
}
@@ -562,7 +623,51 @@ internal class MessageStore : IDisposable
cmd.CommandTimeout = 600;
deleted = cmd.ExecuteNonQuery();
}
PerformMaintenance();
// Skipped when nothing matched: VACUUM rewrites the whole file, and
// running it for zero deleted rows costs seconds on a large database
// for no benefit. DeleteByRetentionPolicy already guards this way.
if (deleted > 0)
{
InvalidateFtsIndex();
TryPerformMaintenance();
}
return deleted;
}
}
// Hard-deletes every message whose ChatType IS in the list, then VACUUMs.
// Returns the number of rows deleted.
//
// The mirror image of CleanupRetainOnly, and the privacy filter needs both.
// With the unknown-channel failsafe on, the rule keeps every channel this
// build does not recognise -- and a retain-list can only name the ones that
// were already in the database when the list was built, so a channel whose
// first message arrives after that would be deleted. Naming what goes
// instead of what stays removes the window entirely.
internal long CleanupDeleteTypes(IReadOnlyCollection<int> deleteTypes)
{
if (deleteTypes.Count == 0)
return 0;
lock (_readLock)
{
long deleted;
using (var cmd = Connection.CreateCommand())
{
var placeholders = BindIntList(cmd, "dt", deleteTypes);
cmd.CommandText = $"DELETE FROM messages WHERE ChatType IN ({placeholders});";
cmd.CommandTimeout = 600;
deleted = cmd.ExecuteNonQuery();
}
if (deleted > 0)
{
InvalidateFtsIndex();
TryPerformMaintenance();
}
return deleted;
}
}
@@ -581,6 +686,33 @@ internal class MessageStore : IDisposable
}
}
// Runs maintenance and swallows a failure, for the delete paths only.
//
// VACUUM needs the database to itself, and a lazily consumed reader on the
// primary connection -- which GetMostRecentMessages hands out and the
// refilter walks outside the lock -- makes it fail immediately with "cannot
// VACUUM - SQL statements in progress". That happens after the DELETE has
// committed, so letting it escape means the caller reports "nothing was
// removed" about a wipe that emptied the database.
//
// The rows are gone either way. An uncompacted file is a housekeeping
// problem; telling somebody their history is still there when it is not is
// a different kind of problem.
private void TryPerformMaintenance()
{
try
{
PerformMaintenance();
}
catch (Exception e)
{
_logger.LogWarning(
e,
"Maintenance after a delete failed; the rows are gone but the file was not compacted."
);
}
}
private string LogPath => DbPath + "-wal";
internal long DatabaseSize() => !File.Exists(DbPath) ? 0 : new FileInfo(DbPath).Length;
@@ -643,9 +775,21 @@ internal class MessageStore : IDisposable
internal SqliteConnection OpenSecondaryConnection()
{
var conn = new SqliteConnection(BuildConnectionString(DbPath));
conn.Open();
ApplyPragmas(conn);
return conn;
try
{
conn.Open();
ApplyPragmas(conn);
return conn;
}
catch
{
// Open can succeed and ApplyPragmas still throw: journal_mode=WAL
// needs a lock and gives up after DefaultTimeout. Without this the
// connection is neither returned nor closed, and with Pooling=false
// it survives until a finalizer gets to it.
conn.Dispose();
throw;
}
}
// Worker-only mutator. The bulk-insert worker is the single legitimate
@@ -797,8 +941,7 @@ internal class MessageStore : IDisposable
// storage form on both sides so the IN(...) compare matches. SQLite has a
// hard parameter limit of 999 in default builds, so we chunk the input --
// a 1000-hit FTS query never explodes the SELECT. Result ordering is not
// guaranteed; callers re-sort (e.g. DbViewer sorts by Date descending in
// Sub-Task 4.4).
// guaranteed; callers re-sort (DbViewer sorts by Date descending).
public IReadOnlyList<Message> LoadByGuids(IReadOnlyList<string> guidStrings)
{
if (guidStrings.Count == 0)
@@ -909,53 +1052,57 @@ internal class MessageStore : IDisposable
// Streams messages for export, sorted ascending by Date, excluding soft-deleted rows.
// Optional filters: chatTypes, from/to inclusive date range.
// Caller is responsible for disposing the enumerator.
// Lock caveat: lock guards command setup and ExecuteReader; the returned
// MessageEnumerator is iterated lazily by the caller outside the lock.
// Acceptable for v1.4.8 -- DbViewer iterates on its filter-worker Task and
// any clash with UpsertMessage on the primary Connection is rare and
// serialised by SQLite's own connection-level lock. v1.5.x DI cycle should
// address this with a snapshot-to-list or connection pool.
// Caller is responsible for disposing the enumerator and the connection.
//
// Takes a caller-owned connection from OpenSecondaryConnection rather than
// using the primary one, and therefore takes no lock. The reader stays open
// for as long as the export writes, which is seconds to minutes on a large
// history, and chat keeps arriving throughout -- so the primary connection
// would be read here and written by UpsertMessage at the same time, and
// SqliteConnection is not thread-safe. Holding _readLock for the whole
// export would trade that for freezing the game instead.
//
// WAL gives readers their own snapshot, so a live write cannot tear the
// export mid-file either.
internal MessageEnumerator StreamForExport(
SqliteConnection conn,
IReadOnlyCollection<int>? chatTypes,
DateTimeOffset? from,
DateTimeOffset? to
)
{
lock (_readLock)
{
var cmd = Connection.CreateCommand();
var cmd = conn.CreateCommand();
var clauses = new List<string> { "deleted = false" };
if (chatTypes is { Count: > 0 })
clauses.Add($"ChatType IN ({BindIntList(cmd, "exct", chatTypes)})");
if (from is not null)
clauses.Add("Date >= $From");
if (to is not null)
clauses.Add("Date <= $To");
var clauses = new List<string> { "deleted = false" };
if (chatTypes is { Count: > 0 })
clauses.Add($"ChatType IN ({BindIntList(cmd, "exct", chatTypes)})");
if (from is not null)
clauses.Add("Date >= $From");
if (to is not null)
clauses.Add("Date <= $To");
cmd.CommandText =
@"
cmd.CommandText =
@"
SELECT
Id, Receiver, ContentId, Date, ChatType, SourceKind, TargetKind,
Sender, Content, SenderSource, ContentSource, ExtraChatChannel
FROM messages
WHERE "
+ string.Join(" AND ", clauses)
+ @"
+ string.Join(" AND ", clauses)
+ @"
ORDER BY Date ASC;";
cmd.CommandTimeout = 600;
cmd.CommandTimeout = 600;
if (from is not null)
cmd.Parameters.AddWithValue("$From", from.Value.ToUnixTimeMilliseconds());
if (to is not null)
cmd.Parameters.AddWithValue("$To", to.Value.ToUnixTimeMilliseconds());
if (from is not null)
cmd.Parameters.AddWithValue("$From", from.Value.ToUnixTimeMilliseconds());
if (to is not null)
cmd.Parameters.AddWithValue("$To", to.Value.ToUnixTimeMilliseconds());
return new MessageEnumerator(
cmd.ExecuteReader(),
_loggerFactory.CreateLogger<MessageEnumerator>()
);
}
// Logger first: an argument list evaluates left to right, so a throwing
// CreateLogger -- which is what a disposed host gives you -- would leave
// an open reader that no MessageEnumerator owns.
var logger = _loggerFactory.CreateLogger<MessageEnumerator>();
return new MessageEnumerator(cmd.ExecuteReader(), logger);
}
// Returns the most recent messages, oldest-first.
@@ -1014,7 +1161,8 @@ internal class MessageStore : IDisposable
}
// Returns up to `limit` tells exchanged with the named player, oldest-first.
// SQL narrows by Receiver + ChatType via the (Receiver, Date) index, then
// SQL narrows by Receiver + ChatType via the (Receiver, Date) index (migration
// 5; before that the ordering fell back to a temp b-tree over all rows), then
// the client-side loop runs PlayerPayload comparison and breaks once
// `limit` partner matches accumulate. Earlier versions had a hardcoded
// 500-row scan cap that cut less-frequent pinned partners off the back of
+1 -1
View File
@@ -2,7 +2,7 @@ using HellionChat.Resources;
namespace HellionChat;
// UI-7: how a sender's name is rendered in the chat log. Kept in its own file
// How a sender's name is rendered in the chat log. Kept in its own file
// (no Dalamud usings) so the SenderNameFormatter pure-helper test stays
// AppDomain-isolated (feedback_dalamud_test_isolation).
Executable → Regular
+450 -411
View File
File diff suppressed because it is too large Load Diff
+630 -165
View File
File diff suppressed because it is too large Load Diff
+285 -16
View File
@@ -15,7 +15,7 @@ namespace HellionChat;
// Builds the generic-host DI container that drives v1.5.0+. The factory is
// invoked synchronously from Plugin.ctor (after the schema gate clears) so the
// container exists before PluginLifecycle.LoadAsync runs. See plan §1 for the
// container exists before PluginLifecycle.LoadAsync runs. For the
// deliberate divergence from Lightless' deferred Func-delegate pattern.
internal static class PluginHostFactory
{
@@ -29,6 +29,15 @@ internal static class PluginHostFactory
logging.AddDalamudLogging(dependencies.PluginLog);
logging.SetMinimumLevel(LogLevel.Trace);
})
// ValidateOnBuild eagerly instantiates every singleton at Build time
// so missing registrations / ConstructorCallSite cycles throw on
// load instead of producing a silent hang. ValidateScopes is cheap
// (we only use singletons) but guards against future Scoped misuse.
.UseDefaultServiceProvider(o =>
{
o.ValidateOnBuild = true;
o.ValidateScopes = true;
})
.ConfigureServices(services => ConfigureServices(services, plugin, dependencies))
.Build();
}
@@ -39,7 +48,7 @@ internal static class PluginHostFactory
PluginHostDependencies dependencies
)
{
// Block A — Dalamud services (21 [PluginService] singletons).
// Dalamud services (21 [PluginService] singletons).
services.AddSingleton(dependencies);
services.AddSingleton(dependencies.PluginInterface);
services.AddSingleton(dependencies.PluginLog);
@@ -68,7 +77,7 @@ internal static class PluginHostFactory
services.AddSingleton(plugin.WindowSystem);
services.AddSingleton<PluginLifecycle>();
// Block B — HellionChat singletons. Factory lambdas because most
// HellionChat singletons. Factory lambdas because most
// classes are internal-sealed and the default activator only sees
// public ctors.
services.AddSingleton<IPlatformUtil>(_ => new DalamudPlatformUtil());
@@ -80,7 +89,6 @@ internal static class PluginHostFactory
services.AddSingleton(sp => new FontManager(
sp.GetRequiredService<IDalamudPluginInterface>()
));
services.AddSingleton(_ => new StatusBar());
services.AddSingleton(sp => new IpcManager(sp.GetRequiredService<ILogger<IpcManager>>()));
services.AddSingleton(sp => new ExtraChat(sp.GetRequiredService<ILogger<ExtraChat>>()));
@@ -92,6 +100,23 @@ internal static class PluginHostFactory
sp.GetRequiredService<ILogger<ThemeRegistry>>()
));
services.AddSingleton(_ => new Ui.StyleEngine.TokenResolver());
// Transient: each surface owns its motes, so two backdrops on screen do
// not drift in lockstep.
services.AddSingleton(sp => new Ui.Components.Settings.SectionRenderer(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
services.AddTransient(sp => new Ui.StyleEngine.SurfaceBackdrop(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
services.AddSingleton(sp => new Ui.StyleEngine.PushStack(
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
services.AddSingleton(sp => new GameFunctions.GameFunctions(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<ILogger<GameFunctions.GameFunctions>>(),
@@ -99,6 +124,7 @@ internal static class PluginHostFactory
));
services.AddSingleton(sp => new TypingIpc(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<Ui.Components.InputBar>(),
sp.GetRequiredService<ILogger<TypingIpc>>()
));
@@ -107,6 +133,137 @@ internal static class PluginHostFactory
sp.GetRequiredService<ILogger<Integrations.HonorificService>>(),
sp.GetRequiredService<IFramework>()
));
services.AddSingleton(sp => new Services.TellRouterService(
sp.GetRequiredService<MessageManager>(),
sp.GetRequiredService<ILogger<Services.TellRouterService>>()
));
services.AddSingleton(sp => new Ui.Components.HonorificHeader(
sp.GetRequiredService<Integrations.HonorificService>(),
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
services.AddSingleton(sp => new Ui.Components.Sidebar(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>(),
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<ILogger<Ui.Components.Sidebar>>(),
sp.GetRequiredService<Ui.Windows.ChannelPopoutPool>()
));
services.AddSingleton(sp => new Ui.Components.MessageList(
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<Ui.Components.ChunkRenderer>()
));
services.AddSingleton(_ => new Ui.Components.SymbolPicker());
services.AddSingleton(sp => new Ui.Components.ThemeQuickPicker(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Plugin>()
));
services.AddSingleton(sp => new Ui.Components.InputBar(
sp.GetRequiredService<Ui.Components.SymbolPicker>(),
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>(),
sp.GetRequiredService<ILogger<Ui.Components.InputBar>>(),
() => sp.GetRequiredService<Plugin>().SettingsWindow.Toggle(),
sp.GetRequiredService<Ui.CommandHelpWindow>(),
sp.GetRequiredService<Ui.Components.ThemeQuickPicker>(),
() => sp.GetRequiredService<Plugin>().MainWindow.UserHide()
));
services.AddSingleton(sp => new Ui.Components.Settings.TabSidebar(
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
services.AddSingleton(sp => new Ui.Components.Settings.ContentArea(
sp.GetRequiredService<Ui.StyleEngine.SurfaceBackdrop>()
));
services.AddSingleton(sp => new Ui.Components.Settings.ThemePicker(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<Ui.Components.Settings.SectionRenderer>()
));
services.AddSingleton(sp => new Ui.Components.Settings.ColorPicker(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.Components.Settings.SectionRenderer>()
));
services.AddSingleton(sp => new Ui.Components.Settings.LivePreviewPanel(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>(),
sp.GetRequiredService<FontManager>()
));
services.AddSingleton(sp => new Ui.Components.Settings.ThemeImportExportRow(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<ILogger<Ui.Components.Settings.ThemeImportExportRow>>()
));
services.AddSingleton(sp => new Ui.Components.Settings.FontsSection(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<Ui.Components.Settings.SectionRenderer>()
));
services.AddSingleton(sp => new Ui.Components.Settings.ChatColourPicker(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.Components.Settings.SectionRenderer>()
));
services.AddSingleton(sp => new Ui.Components.Settings.Tabs.AppearanceTab(
sp.GetRequiredService<Ui.Components.Settings.ThemePicker>(),
sp.GetRequiredService<Ui.Components.Settings.ColorPicker>(),
sp.GetRequiredService<Ui.Components.Settings.LivePreviewPanel>(),
sp.GetRequiredService<Ui.Components.Settings.ThemeImportExportRow>(),
sp.GetRequiredService<Ui.Components.Settings.FontsSection>(),
sp.GetRequiredService<Ui.Components.Settings.ChatColourPicker>()
));
services.AddSingleton(sp => new Ui.Components.Settings.Tabs.GeneralTab(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
services.AddSingleton(sp => new Ui.Components.Settings.Tabs.ChatTab(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
services.AddSingleton(sp => new Ui.Components.Settings.Tabs.WindowTab(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
services.AddSingleton(sp => new Ui.Components.Settings.Tabs.ChannelsTab(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
services.AddSingleton(sp => new Ui.Components.Settings.Tabs.DataPrivacyTab(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>(),
sp.GetRequiredService<ILogger<Ui.Components.Settings.Tabs.DataPrivacyTab>>()
));
services.AddSingleton(sp => new Ui.Components.Settings.Tabs.AboutTab(
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<Integrations.HonorificService>(),
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<IPlatformUtil>()
));
services.AddSingleton(sp => new Ui.Components.StatusBar(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<FontManager>()
));
services.AddSingleton(sp => new Ui.Components.TopTabBar(
sp.GetRequiredService<Ui.Windows.ChannelPopoutPool>(),
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
services.AddSingleton(sp => new Ui.Windows.MainWindow(
sp.GetRequiredService<Ui.Components.HonorificHeader>(),
sp.GetRequiredService<Ui.Components.Sidebar>(),
sp.GetRequiredService<Ui.Components.TopTabBar>(),
sp.GetRequiredService<Ui.Components.MessageList>(),
sp.GetRequiredService<Ui.Components.InputBar>(),
sp.GetRequiredService<Ui.Components.StatusBar>(),
sp.GetRequiredService<Lender<PayloadHandler>>(),
sp.GetRequiredService<Ui.Windows.ChannelPopoutPool>(),
sp.GetRequiredService<Ui.StyleEngine.SurfaceBackdrop>()
));
services.AddSingleton(sp => new Integrations.FailedTellNotifier(
sp.GetRequiredService<ILogger<Integrations.FailedTellNotifier>>()
));
@@ -134,33 +291,116 @@ internal static class PluginHostFactory
);
});
// Block C — Windows. WindowSystem.AddWindow is called from
// PluginLifecycle.LoadAsync on the framework thread.
services.AddSingleton(sp => new ChatLogWindow(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<ILogger<ChatLogWindow>>(),
sp.GetRequiredService<ILoggerFactory>()
// Factory-lambdas for ChunkRenderer, PayloadHandler, and Lender<PayloadHandler>
// because all three are internal-sealed (ActivatorUtilities can't reflect into
// internal ctors) and Lender<T> has an internal ctor by design.
// PayloadHandler registered twice: once as singleton for G/H, once via Lender<T> for per-frame isolation (I/J/K).
services.AddSingleton(sp => new Ui.Components.ChunkRenderer(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<ILogger<Ui.Components.ChunkRenderer>>(),
sp.GetRequiredService<GameFunctions.GameFunctions>()
));
services.AddSingleton(sp => new SettingsWindow(
services.AddSingleton(sp => MakePayloadHandler(sp));
services.AddSingleton(sp => new Lender<PayloadHandler>(() => MakePayloadHandler(sp)));
// Pop-out windows: each gets its OWN MessageList + InputBar so the
// channel pill and message scroll are per-window. The PayloadHandler is
// attached post-build (ChannelPopoutInitHostedService), NEVER via ctor
// (would close a silent FactoryCallSite cycle).
services.AddSingleton<Func<int, Ui.Windows.ChannelPopoutWindow>>(sp =>
slot => new Ui.Windows.ChannelPopoutWindow(
slot,
new Ui.Components.MessageList(
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<Ui.Components.ChunkRenderer>()
),
new Ui.Components.InputBar(
sp.GetRequiredService<Ui.Components.SymbolPicker>(),
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>(),
sp.GetRequiredService<ILogger<Ui.Components.InputBar>>(),
() => sp.GetRequiredService<Plugin>().SettingsWindow.Toggle(),
sp.GetRequiredService<Ui.CommandHelpWindow>()
),
sp.GetRequiredService<ILogger<Ui.Windows.ChannelPopoutWindow>>(),
sp.GetRequiredService<FontManager>(),
sp.GetRequiredService<Ui.StyleEngine.SurfaceBackdrop>(),
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
)
);
services.AddSingleton(sp => new Ui.Windows.ChannelPopoutPool(
sp.GetRequiredService<Func<int, Ui.Windows.ChannelPopoutWindow>>(),
sp.GetRequiredService<ILogger<Ui.Windows.ChannelPopoutPool>>()
));
// Windows. WindowSystem.AddWindow is called from
// PluginLifecycle.LoadAsync on the framework thread.
services.AddSingleton(sp => new Ui.Windows.SettingsWindow(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<Ui.Components.Settings.TabSidebar>(),
sp.GetRequiredService<Ui.Components.Settings.ContentArea>(),
sp.GetRequiredService<Ui.Components.Settings.ThemePicker>(),
sp.GetRequiredService<Ui.Components.Settings.ColorPicker>(),
sp.GetRequiredService<Ui.Components.Settings.LivePreviewPanel>(),
sp.GetRequiredService<Ui.Components.Settings.Tabs.AppearanceTab>(),
sp.GetRequiredService<Ui.Components.Settings.Tabs.GeneralTab>(),
sp.GetRequiredService<Ui.Components.Settings.Tabs.ChatTab>(),
sp.GetRequiredService<Ui.Components.Settings.Tabs.WindowTab>(),
sp.GetRequiredService<Ui.Components.Settings.Tabs.ChannelsTab>(),
sp.GetRequiredService<Ui.Components.Settings.Tabs.DataPrivacyTab>(),
sp.GetRequiredService<Ui.Components.Settings.Tabs.AboutTab>(),
sp.GetRequiredService<ILoggerFactory>()
));
services.AddSingleton(sp => new DbViewer(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<ILogger<DbViewer>>()
));
services.AddSingleton(sp => new InputPreview(sp.GetRequiredService<ChatLogWindow>()));
services.AddSingleton(sp => new CommandHelpWindow(sp.GetRequiredService<ChatLogWindow>()));
services.AddSingleton(sp => new InputPreview(
sp.GetRequiredService<Ui.Components.ChunkRenderer>(),
sp.GetRequiredService<Lender<PayloadHandler>>(),
sp.GetRequiredService<Ui.Windows.MainWindow>(),
sp.GetRequiredService<Ui.Components.InputBar>(),
sp.GetRequiredService<ILogger<InputPreview>>()
));
// No MainWindow ctor-param: breaks the InputBar -> CommandHelpWindow ->
// MainWindow -> InputBar singleton cycle. MainWindow is wired post-build
// via CommandHelpWindowInitHostedService.
services.AddSingleton(sp => new CommandHelpWindow(
sp.GetRequiredService<Ui.Components.ChunkRenderer>(),
sp.GetRequiredService<ILogger<CommandHelpWindow>>()
));
services.AddSingleton(sp => new SeStringDebugger(sp.GetRequiredService<Plugin>()));
services.AddSingleton(sp => new DebuggerWindow(sp.GetRequiredService<Plugin>()));
services.AddSingleton(sp => new FirstRunWizard(sp.GetRequiredService<Plugin>()));
#if DEBUG
services.AddSingleton(sp => new Ui.Windows.WidgetGalleryWindow(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<Ui.StyleEngine.TokenResolver>()
));
#endif
// The style lab: variants side by side, in-game, against the live theme.
// Permanent, and deliberately not behind DEBUG: style decisions get
// made in the build that actually ships.
services.AddSingleton(sp => new Ui.Windows.InputBarLabWindow(
sp.GetRequiredService<Plugin>()
));
services.AddSingleton(sp => new DebuggerWindow(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<PayloadHandler>()
));
services.AddSingleton(sp => new FirstRunWizard(
sp.GetRequiredService<Plugin>(),
sp.GetRequiredService<Ui.StyleEngine.SurfaceBackdrop>()
));
// Hosted-service adapters: thin wrappers around the existing init
// methods so the service class bodies stay unchanged. FontManager
// does not need one — its ctor runs the init inline inside a single
// SuppressAutoRebuild block on eager resolve.
services.AddHostedService(sp => new ThemeRegistryInitHostedService(
sp.GetRequiredService<ThemeRegistry>()
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<FontManager>()
));
services.AddHostedService(sp => new IpcManagerInitHostedService(
sp.GetRequiredService<IpcManager>()
@@ -178,12 +418,41 @@ internal static class PluginHostFactory
services.AddHostedService(sp => new AutoTellTabsServiceInitHostedService(
sp.GetRequiredService<AutoTellTabsService>()
));
// Must come AFTER AutoTell's registration: both subscribe MessageProcessed,
// and AutoTell subscribing first lets the router's IsOpen-guard see the
// already-opened pop-out (FIFO framework-tick ordering, no double-pop).
services.AddHostedService(sp => new TellRouterServiceInitHostedService(
sp.GetRequiredService<Services.TellRouterService>()
));
services.AddHostedService(
sp => new Infrastructure.Hosting.FailedTellNotifierInitHostedService(
sp.GetRequiredService<Integrations.FailedTellNotifier>()
)
);
services.AddHostedService(sp => new PayloadHandlerInitHostedService(
sp.GetRequiredService<PayloadHandler>(),
sp.GetRequiredService<Ui.Components.MessageList>()
));
services.AddHostedService(sp => new CommandHelpWindowInitHostedService(
sp.GetRequiredService<Ui.CommandHelpWindow>(),
sp.GetRequiredService<Ui.Windows.MainWindow>()
));
services.AddHostedService(sp => new ChannelPopoutInitHostedService(
sp.GetRequiredService<Ui.Windows.ChannelPopoutPool>(),
sp.GetRequiredService<PayloadHandler>()
));
}
private static PayloadHandler MakePayloadHandler(IServiceProvider sp) =>
new(
sp.GetRequiredService<ThemeRegistry>(),
sp.GetRequiredService<IpcManager>(),
sp.GetRequiredService<GameFunctions.GameFunctions>(),
sp.GetRequiredService<Ui.Components.InputBar>(),
sp.GetRequiredService<Ui.Windows.MainWindow>(),
sp.GetRequiredService<Ui.Components.ChunkRenderer>(),
sp.GetRequiredService<ILogger<PayloadHandler>>()
);
}
internal sealed record PluginHostDependencies(
+11 -2
View File
@@ -58,14 +58,23 @@ internal sealed class PluginLifecycle : IAsyncDisposable
private static void RegisterWindows(Plugin plugin)
{
plugin.WindowSystem.AddWindow(plugin.ChatLogWindow);
plugin.WindowSystem.AddWindow(plugin.MainWindow);
plugin.WindowSystem.AddWindow(plugin.SettingsWindow);
plugin.WindowSystem.AddWindow(plugin.DbViewer);
plugin.WindowSystem.AddWindow(plugin.InputPreview);
plugin.WindowSystem.AddWindow(Plugin.InputPreview);
plugin.WindowSystem.AddWindow(plugin.CommandHelpWindow);
plugin.WindowSystem.AddWindow(plugin.SeStringDebugger);
#if DEBUG
plugin.WindowSystem.AddWindow(plugin.WidgetGallery);
#endif
plugin.WindowSystem.AddWindow(plugin.InputBarLab);
plugin.WindowSystem.AddWindow(plugin.DebuggerWindow);
plugin.WindowSystem.AddWindow(plugin.FirstRunWizard);
// Pop-out pool: register all pre-allocated instances ONCE here on the
// framework thread. Open/Close at runtime is IsOpen-only, never AddWindow.
foreach (var popout in plugin.ChannelPopoutPool.Instances)
plugin.WindowSystem.AddWindow(popout);
}
public async ValueTask DisposeAsync()
+154
View File
@@ -0,0 +1,154 @@
using HellionChat.Code;
using HellionChat.Resources;
namespace HellionChat.Privacy;
// The eight buckets the privacy surface sorts channels into. Eighty-nine
// checkboxes in one flat list is not a choice anybody makes; eight named groups
// is. Shared by the export form and the persist grid so the two screens
// describe channels the same way.
//
// Headings are functions, not strings, so a language switch at runtime relabels
// them on the next frame. A captured string would keep the language the window
// happened to be opened in.
//
// Game Master channels follow ChatTypeExt.Parent(), which already pairs each of
// them with its player counterpart. Filing them all under system traffic reads
// tidier but puts GmTell -- a private two-person conversation -- outside the
// direct-messages group, and an access request that quietly drops part of what
// it promises is the dangerous kind of gap.
//
// Every ChatType belongs to exactly one group, and a build-suite test pins that.
// A channel in no group cannot be picked in any of these screens, which reads as
// a missing checkbox rather than as an omission.
internal static class ChannelGroups
{
internal static readonly (Func<string> Heading, ChatType[] Types)[] All =
[
(
() => HellionStrings.Privacy_Group_DirectMessages,
[ChatType.TellIncoming, ChatType.TellOutgoing, ChatType.GmTell]
),
(
() => HellionStrings.Privacy_Group_PartyAlliance,
[
ChatType.Party,
ChatType.CrossParty,
ChatType.Alliance,
ChatType.PvpTeam,
ChatType.PvpTeamAnnouncement,
ChatType.PvpTeamLoginLogout,
ChatType.GmParty,
]
),
(
() => HellionStrings.Privacy_Group_FreeCompany,
[
ChatType.FreeCompany,
ChatType.FreeCompanyAnnouncement,
ChatType.FreeCompanyLoginLogout,
ChatType.GmFreeCompany,
]
),
(
() => HellionStrings.Privacy_Group_Linkshells,
[
ChatType.Linkshell1,
ChatType.Linkshell2,
ChatType.Linkshell3,
ChatType.Linkshell4,
ChatType.Linkshell5,
ChatType.Linkshell6,
ChatType.Linkshell7,
ChatType.Linkshell8,
ChatType.GmLinkshell1,
ChatType.GmLinkshell2,
ChatType.GmLinkshell3,
ChatType.GmLinkshell4,
ChatType.GmLinkshell5,
ChatType.GmLinkshell6,
ChatType.GmLinkshell7,
ChatType.GmLinkshell8,
]
),
(
() => HellionStrings.Privacy_Group_CrossLinkshells,
[
ChatType.CrossLinkshell1,
ChatType.CrossLinkshell2,
ChatType.CrossLinkshell3,
ChatType.CrossLinkshell4,
ChatType.CrossLinkshell5,
ChatType.CrossLinkshell6,
ChatType.CrossLinkshell7,
ChatType.CrossLinkshell8,
]
),
(
() => HellionStrings.Privacy_Group_ExtraChat,
[
ChatType.ExtraChatLinkshell1,
ChatType.ExtraChatLinkshell2,
ChatType.ExtraChatLinkshell3,
ChatType.ExtraChatLinkshell4,
ChatType.ExtraChatLinkshell5,
ChatType.ExtraChatLinkshell6,
ChatType.ExtraChatLinkshell7,
ChatType.ExtraChatLinkshell8,
]
),
(
() => HellionStrings.Privacy_Group_PublicChat,
[
ChatType.Say,
ChatType.Shout,
ChatType.Yell,
ChatType.NoviceNetwork,
ChatType.NoviceNetworkSystem,
ChatType.CustomEmote,
ChatType.StandardEmote,
ChatType.GmSay,
ChatType.GmShout,
ChatType.GmYell,
ChatType.GmNoviceNetwork,
]
),
(
() => HellionStrings.Privacy_Group_SystemLogs,
[
ChatType.System,
ChatType.Notice,
ChatType.Urgent,
ChatType.Echo,
ChatType.NpcDialogue,
ChatType.NpcAnnouncement,
ChatType.LootNotice,
ChatType.LootRoll,
ChatType.RetainerSale,
ChatType.Crafting,
ChatType.Gathering,
ChatType.Sign,
ChatType.RandomNumber,
ChatType.MessageBook,
ChatType.Alarm,
ChatType.Orchestrion,
ChatType.GlamourNotifications,
ChatType.PeriodicRecruitmentNotification,
ChatType.GatheringSystem,
ChatType.Progress,
ChatType.Debug,
ChatType.Error,
ChatType.Item,
ChatType.Action,
ChatType.BattleSystem,
ChatType.Damage,
ChatType.Healing,
ChatType.Miss,
ChatType.GainBuff,
ChatType.GainDebuff,
ChatType.LoseBuff,
ChatType.LoseDebuff,
]
),
];
}
+1 -1
View File
@@ -4,7 +4,7 @@ namespace HellionChat.Privacy;
internal static class PrivacyDefaults
{
// F3.1: failsafe for ChatTypes added by future FFXIV patches. New installs
// Failsafe for ChatTypes added by future FFXIV patches. New installs
// persist unknown channels so a major patch's added ChatType isn't silently
// dropped before the user can opt in or out. Existing configs keep their
// explicit choice — see Configuration.cs PrivacyPersistUnknownChannels.
+51
View File
@@ -0,0 +1,51 @@
namespace HellionChat.Privacy;
// The rule that decides whether a message is written to disk, as plain logic.
//
// It lives apart from Configuration because Configuration implements a Dalamud
// interface, and the build suite cannot load Dalamud.dll -- the runtime resolves
// the declaring type before it ever reaches the method body, so even a static
// call on it fails. This is the single most consequential branch in the plugin,
// and it belongs where it can be pinned.
internal static class StorageRule
{
// v1.12.0 corrected the last term. A known channel the user had unticked
// used to fall through to the unknown-type failsafe, so the channel grid did
// nothing at all whenever that failsafe was on. It is on by default, so the
// filter stored everything while its own description promised "only messages
// from allowed channels are written to the database".
internal static bool Allows(bool listed, bool knownType, bool persistUnknownTypes) =>
listed || (!knownType && persistUnknownTypes);
// Carry-over for configs written before that correction. Where the failsafe
// made the list irrelevant and no channel was ever picked, the old rule
// stored everything; the corrected rule would store nothing. Switching the
// filter off keeps the behaviour and states it where the user can see it.
//
// A config that does have picks keeps them and starts honouring them, which
// is the point of the change.
internal static bool ShouldDisableFilterOnV24(
bool filterEnabled,
bool persistUnknownTypes,
int listedCount
) => filterEnabled && persistUnknownTypes && listedCount == 0;
// Why a retroactive cleanup cannot be offered, or that it can.
internal enum CleanupAvailability
{
Available,
// Nothing is filtered, so nothing in the database contradicts the rule.
FilterDisabled,
// The rule keeps no channel at all. CleanupRetainOnly refuses an empty
// allowlist on purpose -- that request is a full wipe, and a full wipe
// has its own button with its own confirmation.
NothingListed,
}
internal static CleanupAvailability CleanupState(bool filterEnabled, int listedCount) =>
!filterEnabled ? CleanupAvailability.FilterDisabled
: listedCount == 0 ? CleanupAvailability.NothingListed
: CleanupAvailability.Available;
}
+119 -46
View File
@@ -59,11 +59,10 @@ internal class HellionStrings
internal static string Privacy_PersistUnknown_Name => Get(nameof(Privacy_PersistUnknown_Name));
internal static string Privacy_PersistUnknown_Description => Get(nameof(Privacy_PersistUnknown_Description));
internal static string Cleanup_Heading => Get(nameof(Cleanup_Heading));
internal static string Cleanup_Unavailable_FilterOff => Get(nameof(Cleanup_Unavailable_FilterOff));
internal static string Cleanup_Unavailable_NothingListed => Get(nameof(Cleanup_Unavailable_NothingListed));
internal static string Cleanup_Help_Intro => Get(nameof(Cleanup_Help_Intro));
internal static string Cleanup_Help_SavedNote => Get(nameof(Cleanup_Help_SavedNote));
internal static string Cleanup_Preview_Stale => Get(nameof(Cleanup_Preview_Stale));
internal static string Retention_Help_SavedNote => Get(nameof(Retention_Help_SavedNote));
internal static string Cleanup_RefreshPreview => Get(nameof(Cleanup_RefreshPreview));
internal static string Cleanup_NoPreview => Get(nameof(Cleanup_NoPreview));
internal static string Cleanup_TotalStored => Get(nameof(Cleanup_TotalStored));
@@ -92,8 +91,8 @@ internal class HellionStrings
internal static string Retention_Tag_Global => Get(nameof(Retention_Tag_Global));
internal static string Retention_Reset_Button => Get(nameof(Retention_Reset_Button));
internal static string Retention_Apply_Label => Get(nameof(Retention_Apply_Label));
internal static string Retention_Apply_Tooltip => Get(nameof(Retention_Apply_Tooltip));
internal static string Retention_Running => Get(nameof(Retention_Running));
internal static string Retention_RunNow_Tooltip => Get(nameof(Retention_RunNow_Tooltip));
internal static string Retention_LastRun_Never => Get(nameof(Retention_LastRun_Never));
internal static string Retention_LastRun_At => Get(nameof(Retention_LastRun_At));
internal static string Retention_Success => Get(nameof(Retention_Success));
@@ -117,10 +116,12 @@ internal class HellionStrings
internal static string Wizard_Step1_Title => Get(nameof(Wizard_Step1_Title));
internal static string Wizard_Step1_Subtitle => Get(nameof(Wizard_Step1_Subtitle));
internal static string Wizard_Step1_Footer_Hint => Get(nameof(Wizard_Step1_Footer_Hint));
internal static string Wizard_Step1_PluginNotice => Get(nameof(Wizard_Step1_PluginNotice));
internal static string Wizard_Step1_Heritage => Get(nameof(Wizard_Step1_Heritage));
internal static string Wizard_Step1_Skip_Label => Get(nameof(Wizard_Step1_Skip_Label));
internal static string Wizard_Step1_Skip_Tooltip => Get(nameof(Wizard_Step1_Skip_Tooltip));
internal static string Wizard_Step2_Title => Get(nameof(Wizard_Step2_Title));
internal static string Wizard_Step2_RecommendedFooter => Get(nameof(Wizard_Step2_RecommendedFooter));
internal static string Wizard_Profile_Recommended_Badge => Get(nameof(Wizard_Profile_Recommended_Badge));
internal static string Wizard_Profile_Roleplay_Heading => Get(nameof(Wizard_Profile_Roleplay_Heading));
internal static string Wizard_Profile_Roleplay_Description => Get(nameof(Wizard_Profile_Roleplay_Description));
internal static string Wizard_Profile_Roleplay_Apply => Get(nameof(Wizard_Profile_Roleplay_Apply));
@@ -131,7 +132,6 @@ internal class HellionStrings
internal static string Wizard_Step3_Section_History => Get(nameof(Wizard_Step3_Section_History));
internal static string Wizard_Step3_Section_TellTabs => Get(nameof(Wizard_Step3_Section_TellTabs));
internal static string Wizard_Step3_Section_Visual => Get(nameof(Wizard_Step3_Section_Visual));
internal static string Wizard_Step3_LoadPreviousSession_Label => Get(nameof(Wizard_Step3_LoadPreviousSession_Label));
internal static string Wizard_Step3_FilterIncludePreviousSessions_Label => Get(nameof(Wizard_Step3_FilterIncludePreviousSessions_Label));
internal static string Wizard_Step3_AutoTellTabsHistoryPreload_Label => Get(nameof(Wizard_Step3_AutoTellTabsHistoryPreload_Label));
internal static string Wizard_Step3_UseCompactDensity_Label => Get(nameof(Wizard_Step3_UseCompactDensity_Label));
@@ -144,10 +144,10 @@ internal class HellionStrings
internal static string Wizard_Step4_Summary_TellTabs => Get(nameof(Wizard_Step4_Summary_TellTabs));
internal static string Wizard_Step4_Summary_Visual => Get(nameof(Wizard_Step4_Summary_Visual));
internal static string Wizard_Step4_Summary_Unchanged => Get(nameof(Wizard_Step4_Summary_Unchanged));
internal static string Wizard_Step4_Summary_Off => Get(nameof(Wizard_Step4_Summary_Off));
internal static string Wizard_Step4_TestHint => Get(nameof(Wizard_Step4_TestHint));
internal static string Wizard_Step4_SettingsHint => Get(nameof(Wizard_Step4_SettingsHint));
internal static string Export_Heading => Get(nameof(Export_Heading));
internal static string Export_Help => Get(nameof(Export_Help));
internal static string Export_Range_Label => Get(nameof(Export_Range_Label));
internal static string Export_Sender_Label => Get(nameof(Export_Sender_Label));
@@ -202,8 +202,6 @@ internal class HellionStrings
internal static string AutoTellTabs_UnGreetedTooltip => Get(nameof(AutoTellTabs_UnGreetedTooltip));
internal static string PinTab_MenuPin => Get(nameof(PinTab_MenuPin));
internal static string PinTab_MenuUnpin => Get(nameof(PinTab_MenuUnpin));
internal static string PinTab_MenuPromote => Get(nameof(PinTab_MenuPromote));
internal static string PinTab_PromoteTooltip => Get(nameof(PinTab_PromoteTooltip));
internal static string PinTab_LimitReached => Get(nameof(PinTab_LimitReached));
internal static string PinTab_PinnedTooltip => Get(nameof(PinTab_PinnedTooltip));
internal static string PinTab_PinTooltip => Get(nameof(PinTab_PinTooltip));
@@ -233,8 +231,6 @@ internal class HellionStrings
internal static string Privacy_AutoTellTabs_Preload_Hint => Get(nameof(Privacy_AutoTellTabs_Preload_Hint));
// Hellion Chat — Settings UX Polish v10 wipe migration
internal static string SettingsRefactor_Migration_Title => Get(nameof(SettingsRefactor_Migration_Title));
internal static string SettingsRefactor_Migration_Content => Get(nameof(SettingsRefactor_Migration_Content));
// Hellion Chat — Settings UX Polish 8-tab structure
internal static string Settings_Tab_General => Get(nameof(Settings_Tab_General));
@@ -246,22 +242,6 @@ internal class HellionStrings
internal static string Settings_Tab_Information => Get(nameof(Settings_Tab_Information));
// v1.1.0 — Settings card-grid overview
internal static string Settings_Card_General_Title => Get(nameof(Settings_Card_General_Title));
internal static string Settings_Card_General_Subtext => Get(nameof(Settings_Card_General_Subtext));
internal static string Settings_Card_Appearance_Title => Get(nameof(Settings_Card_Appearance_Title));
internal static string Settings_Card_Appearance_Subtext => Get(nameof(Settings_Card_Appearance_Subtext));
internal static string Settings_Card_Themes_Title => Get(nameof(Settings_Card_Themes_Title));
internal static string Settings_Card_Themes_Subtext => Get(nameof(Settings_Card_Themes_Subtext));
internal static string Settings_Card_Window_Title => Get(nameof(Settings_Card_Window_Title));
internal static string Settings_Card_Window_Subtext => Get(nameof(Settings_Card_Window_Subtext));
internal static string Settings_Card_Chat_Title => Get(nameof(Settings_Card_Chat_Title));
internal static string Settings_Card_Chat_Subtext => Get(nameof(Settings_Card_Chat_Subtext));
internal static string Settings_Card_Tabs_Title => Get(nameof(Settings_Card_Tabs_Title));
internal static string Settings_Card_Tabs_Subtext => Get(nameof(Settings_Card_Tabs_Subtext));
internal static string Settings_Card_Database_Title => Get(nameof(Settings_Card_Database_Title));
internal static string Settings_Card_Database_Subtext => Get(nameof(Settings_Card_Database_Subtext));
internal static string Settings_Card_Information_Title => Get(nameof(Settings_Card_Information_Title));
internal static string Settings_Card_Information_Subtext => Get(nameof(Settings_Card_Information_Subtext));
// v1.1.0 — Themes-Settings-Tab
internal static string Settings_Tab_Themes => Get(nameof(Settings_Tab_Themes));
@@ -290,12 +270,19 @@ internal class HellionStrings
internal static string Settings_Chat_SymbolPicker_Enable_Description => Get(nameof(Settings_Chat_SymbolPicker_Enable_Description));
// Hellion Chat — Database-Tab section headings
internal static string Settings_Database_Storage_Heading => Get(nameof(Settings_Database_Storage_Heading));
internal static string Settings_Database_Viewer_Heading => Get(nameof(Settings_Database_Viewer_Heading));
internal static string Settings_Database_Stats_Heading => Get(nameof(Settings_Database_Stats_Heading));
internal static string Settings_Database_Busy => Get(nameof(Settings_Database_Busy));
internal static string Settings_Database_ClearHint => Get(nameof(Settings_Database_ClearHint));
internal static string Settings_Database_ClearError => Get(nameof(Settings_Database_ClearError));
internal static string Settings_Database_Op_RetentionSweep => Get(nameof(Settings_Database_Op_RetentionSweep));
internal static string Settings_Database_Op_Export => Get(nameof(Settings_Database_Op_Export));
internal static string Settings_Database_Op_Cleanup => Get(nameof(Settings_Database_Op_Cleanup));
internal static string Settings_Database_Op_Clear => Get(nameof(Settings_Database_Op_Clear));
internal static string Settings_Database_Op_Preview => Get(nameof(Settings_Database_Op_Preview));
internal static string Settings_Database_Op_Maintenance => Get(nameof(Settings_Database_Op_Maintenance));
// Hellion Chat — Default tab presets (channel-themed)
internal static string Tabs_Presets_System => Get(nameof(Tabs_Presets_System));
internal static string Tabs_Presets_Emote => Get(nameof(Tabs_Presets_Emote));
internal static string Tabs_Presets_FreeCompany => Get(nameof(Tabs_Presets_FreeCompany));
internal static string Tabs_Presets_Party => Get(nameof(Tabs_Presets_Party));
internal static string Tabs_Presets_Beginner => Get(nameof(Tabs_Presets_Beginner));
@@ -328,14 +315,8 @@ internal class HellionStrings
internal static string Settings_Window_ResetPosition_Description => Get(nameof(Settings_Window_ResetPosition_Description));
// Hellion Chat — v0.6.0 one-time hint banner shown inside pop-outs
internal static string Popout_v060_HintText => Get(nameof(Popout_v060_HintText));
internal static string Popout_v060_HintAck => Get(nameof(Popout_v060_HintAck));
internal static string Popout_v060_HintOpenSettings => Get(nameof(Popout_v060_HintOpenSettings));
// Hellion Chat — v0.6.1 pop-out header hint banner (discoverability)
internal static string Hint_v061_PopOutHeader_Body => Get(nameof(Hint_v061_PopOutHeader_Body));
internal static string Hint_v061_PopOutHeader_Ack => Get(nameof(Hint_v061_PopOutHeader_Ack));
internal static string Hint_v061_PopOutHeader_OpenSettings => Get(nameof(Hint_v061_PopOutHeader_OpenSettings));
// Hellion Chat — v1.0.0 Chat 2 parallel-load conflict detection
internal static string ChatTwoConflictTitle => Get(nameof(ChatTwoConflictTitle));
@@ -352,7 +333,6 @@ internal class HellionStrings
// Hellion Chat — v1.2.1 Settings Cleanup: new card titles + subtexts
internal static string Settings_Card_DataManagement_Title => Get(nameof(Settings_Card_DataManagement_Title));
internal static string Settings_Card_DataManagement_Subtext => Get(nameof(Settings_Card_DataManagement_Subtext));
// Hellion Chat — v1.2.1 Theme & Layout tab section headings + WindowOpacity slider
internal static string Settings_ThemeAndLayout_Theme_Heading => Get(nameof(Settings_ThemeAndLayout_Theme_Heading));
@@ -364,16 +344,102 @@ internal class HellionStrings
// Hellion Chat — v1.2.1 Data Management tab section headings
internal static string Settings_DataManagement_Advanced_Heading => Get(nameof(Settings_DataManagement_Advanced_Heading));
// v1.5.6: Data & Privacy tab section titles (R6)
// v1.5.6: Data & Privacy tab section titles
internal static string Settings_Section_PrivacyFilter => Get(nameof(Settings_Section_PrivacyFilter));
internal static string Settings_Section_Storage => Get(nameof(Settings_Section_Storage));
internal static string Settings_Section_Retention => Get(nameof(Settings_Section_Retention));
internal static string Settings_Section_Cleanup => Get(nameof(Settings_Section_Cleanup));
internal static string Settings_Section_Export => Get(nameof(Settings_Section_Export));
internal static string Settings_Section_Telemetry => Get(nameof(Settings_Section_Telemetry));
internal static string Settings_Theme_ActiveTheme => Get(nameof(Settings_Theme_ActiveTheme));
internal static string Settings_Theme_ForkAndEdit => Get(nameof(Settings_Theme_ForkAndEdit));
internal static string Settings_Theme_ForkTooltip => Get(nameof(Settings_Theme_ForkTooltip));
internal static string Settings_Theme_EditTheme => Get(nameof(Settings_Theme_EditTheme));
internal static string Settings_Theme_Editing => Get(nameof(Settings_Theme_Editing));
internal static string Settings_Theme_Group_Surfaces => Get(nameof(Settings_Theme_Group_Surfaces));
internal static string Settings_Theme_Group_Borders => Get(nameof(Settings_Theme_Group_Borders));
internal static string Settings_Theme_Group_Text => Get(nameof(Settings_Theme_Group_Text));
internal static string Settings_Theme_Group_Identity => Get(nameof(Settings_Theme_Group_Identity));
internal static string Settings_Theme_Group_Status => Get(nameof(Settings_Theme_Group_Status));
internal static string Settings_Theme_Save => Get(nameof(Settings_Theme_Save));
internal static string Settings_Theme_Cancel => Get(nameof(Settings_Theme_Cancel));
internal static string Settings_Theme_ResetToSource => Get(nameof(Settings_Theme_ResetToSource));
internal static string Settings_Theme_ResetUnavailable => Get(nameof(Settings_Theme_ResetUnavailable));
internal static string Settings_Theme_LockedTooltip => Get(nameof(Settings_Theme_LockedTooltip));
internal static string Settings_Theme_Custom => Get(nameof(Settings_Theme_Custom));
internal static string Settings_Tabs_Duplicate => Get(nameof(Settings_Tabs_Duplicate));
internal static string Settings_Theme_ForkActive => Get(nameof(Settings_Theme_ForkActive));
internal static string Settings_Theme_ImportFile => Get(nameof(Settings_Theme_ImportFile));
internal static string Settings_Theme_ImportPathHint => Get(nameof(Settings_Theme_ImportPathHint));
internal static string Settings_Theme_ExportDialogTitle => Get(nameof(Settings_Theme_ExportDialogTitle));
internal static string Settings_Theme_Category_Cool => Get(nameof(Settings_Theme_Category_Cool));
internal static string Settings_Theme_Category_Natural => Get(nameof(Settings_Theme_Category_Natural));
internal static string Settings_Theme_Category_Classic => Get(nameof(Settings_Theme_Category_Classic));
internal static string Settings_Theme_Category_Retro => Get(nameof(Settings_Theme_Category_Retro));
internal static string Settings_Fonts_Bundled => Get(nameof(Settings_Fonts_Bundled));
internal static string Settings_Fonts_GameFont => Get(nameof(Settings_Fonts_GameFont));
internal static string Settings_Fonts_Global => Get(nameof(Settings_Fonts_Global));
internal static string Settings_Fonts_Active => Get(nameof(Settings_Fonts_Active));
internal static string Settings_Preview_TypeAMessage => Get(nameof(Settings_Preview_TypeAMessage));
internal static string StatusBar_Tabs_One => Get(nameof(StatusBar_Tabs_One));
internal static string StatusBar_Tabs_Other => Get(nameof(StatusBar_Tabs_Other));
internal static string StatusBar_Tells_One => Get(nameof(StatusBar_Tells_One));
internal static string StatusBar_Tells_Other => Get(nameof(StatusBar_Tells_Other));
internal static string StatusBar_Messages => Get(nameof(StatusBar_Messages));
internal static string StatusBar_MessagesThousands => Get(nameof(StatusBar_MessagesThousands));
internal static string Settings_Preview_TitleMock => Get(nameof(Settings_Preview_TitleMock));
internal static string Settings_Preview_StatusOpen => Get(nameof(Settings_Preview_StatusOpen));
internal static string ChannelHeader_NotLoggedIn => Get(nameof(ChannelHeader_NotLoggedIn));
internal static string InputBar_More_Tooltip => Get(nameof(InputBar_More_Tooltip));
internal static string Settings_Section_Links => Get(nameof(Settings_Section_Links));
internal static string Settings_Section_Behaviour => Get(nameof(Settings_Section_Behaviour));
internal static string Settings_Section_Keybinds => Get(nameof(Settings_Section_Keybinds));
internal static string Settings_Section_Notifications => Get(nameof(Settings_Section_Notifications));
internal static string Settings_Section_DisplayModes => Get(nameof(Settings_Section_DisplayModes));
internal static string Settings_Section_History => Get(nameof(Settings_Section_History));
internal static string Settings_Section_CommandHelp => Get(nameof(Settings_Section_CommandHelp));
internal static string Settings_Section_PluginDisclosure => Get(nameof(Settings_Section_PluginDisclosure));
internal static string Settings_Section_LayoutMode => Get(nameof(Settings_Section_LayoutMode));
internal static string Settings_Section_Opacity => Get(nameof(Settings_Section_Opacity));
internal static string Settings_Section_ResizeBehaviour => Get(nameof(Settings_Section_ResizeBehaviour));
internal static string Settings_Section_TellAutoOpen => Get(nameof(Settings_Section_TellAutoOpen));
internal static string Settings_Section_Sidebar => Get(nameof(Settings_Section_Sidebar));
internal static string Settings_Section_Brand => Get(nameof(Settings_Section_Brand));
internal static string Settings_Section_Integrations => Get(nameof(Settings_Section_Integrations));
internal static string Settings_Section_Credits => Get(nameof(Settings_Section_Credits));
internal static string Settings_Section_License => Get(nameof(Settings_Section_License));
internal static string Settings_Keybinds_Hint => Get(nameof(Settings_Keybinds_Hint));
internal static string Settings_Keybinds_CycleNext => Get(nameof(Settings_Keybinds_CycleNext));
internal static string Settings_Keybinds_CyclePrevious => Get(nameof(Settings_Keybinds_CyclePrevious));
internal static string Settings_General_Language_Description => Get(nameof(Settings_General_Language_Description));
internal static string Settings_Chat_Clock24_Name => Get(nameof(Settings_Chat_Clock24_Name));
internal static string Settings_Chat_PreviousSessions_Name => Get(nameof(Settings_Chat_PreviousSessions_Name));
internal static string Settings_Chat_PreviousSessions_Description => Get(nameof(Settings_Chat_PreviousSessions_Description));
internal static string Settings_Chat_CommandHelpSide_Name => Get(nameof(Settings_Chat_CommandHelpSide_Name));
internal static string Settings_Chat_CommandHelpSide_Description => Get(nameof(Settings_Chat_CommandHelpSide_Description));
internal static string Settings_Channels_TellAutoOpenMode_Name => Get(nameof(Settings_Channels_TellAutoOpenMode_Name));
internal static string Settings_Channels_TellAutoOpenMode_Description => Get(nameof(Settings_Channels_TellAutoOpenMode_Description));
internal static string Settings_Channels_TellSwitchAlways_Name => Get(nameof(Settings_Channels_TellSwitchAlways_Name));
internal static string Settings_Channels_TellSwitchAlways_Description => Get(nameof(Settings_Channels_TellSwitchAlways_Description));
internal static string Settings_Window_LayoutSidebar => Get(nameof(Settings_Window_LayoutSidebar));
internal static string Settings_Window_LayoutTopTabs => Get(nameof(Settings_Window_LayoutTopTabs));
internal static string Settings_Window_TabPlacement_Name => Get(nameof(Settings_Window_TabPlacement_Name));
internal static string Settings_Window_TabPlacement_Description => Get(nameof(Settings_Window_TabPlacement_Description));
internal static string Settings_Window_TitleBar_Name => Get(nameof(Settings_Window_TitleBar_Name));
internal static string Settings_Window_PopoutTitleBar_Name => Get(nameof(Settings_Window_PopoutTitleBar_Name));
internal static string Settings_Window_AllowMove_Name => Get(nameof(Settings_Window_AllowMove_Name));
internal static string Settings_Window_AllowResize_Name => Get(nameof(Settings_Window_AllowResize_Name));
internal static string Settings_Window_SidebarThreshold_Name => Get(nameof(Settings_Window_SidebarThreshold_Name));
internal static string Settings_Window_SidebarThreshold_Description => Get(nameof(Settings_Window_SidebarThreshold_Description));
internal static string Settings_Window_PreviewPosition_Name => Get(nameof(Settings_Window_PreviewPosition_Name));
internal static string Settings_Window_PreviewOnlyTyping_Name => Get(nameof(Settings_Window_PreviewOnlyTyping_Name));
internal static string Settings_About_GiteaRepo => Get(nameof(Settings_About_GiteaRepo));
internal static string Settings_About_CustomRepo => Get(nameof(Settings_About_CustomRepo));
internal static string Settings_Section_AutoTranslate => Get(nameof(Settings_Section_AutoTranslate));
internal static string Settings_Telemetry_None => Get(nameof(Settings_Telemetry_None));
internal static string Settings_Section_Database => Get(nameof(Settings_Section_Database));
// Hellion Chat — v1.2.1 Migration v15 → v16 toast
internal static string Migration_v16_OverrideStyle_Toast => Get(nameof(Migration_v16_OverrideStyle_Toast));
// Hellion Chat — v1.3.0 Integrations (Honorific + Coming-Soon roadmap) — now in About tab
internal static string Settings_Integrations_Intro => Get(nameof(Settings_Integrations_Intro));
@@ -413,6 +479,14 @@ internal class HellionStrings
// Hellion Chat — v1.5.4 header quick-picker + reduce-motion toggle
internal static string Settings_QuickPicker_Tooltip => Get(nameof(Settings_QuickPicker_Tooltip));
internal static string InputBar_InsertSymbol_Tooltip =>
Get(nameof(InputBar_InsertSymbol_Tooltip));
internal static string InputBar_Settings_Tooltip => Get(nameof(InputBar_Settings_Tooltip));
internal static string InputBar_HideChat_Tooltip => Get(nameof(InputBar_HideChat_Tooltip));
internal static string InputBar_PopIn_Tooltip => Get(nameof(InputBar_PopIn_Tooltip));
internal static string Settings_QuickPicker_Themes_Header => Get(nameof(Settings_QuickPicker_Themes_Header));
internal static string Settings_QuickPicker_Tabs_Header => Get(nameof(Settings_QuickPicker_Tabs_Header));
internal static string Settings_ThemeAndLayout_ReduceMotion_Name => Get(nameof(Settings_ThemeAndLayout_ReduceMotion_Name));
@@ -461,22 +535,21 @@ internal class HellionStrings
internal static string Settings_General_CustomSoundVolume_Name => Get(nameof(Settings_General_CustomSoundVolume_Name));
internal static string Settings_General_CustomSoundVolume_Description => Get(nameof(Settings_General_CustomSoundVolume_Description));
// v1.5.6: General tab collapsible section titles (R6)
// v1.5.6: General tab collapsible section titles
internal static string Settings_Section_Input => Get(nameof(Settings_Section_Input));
internal static string Settings_Section_Sound => Get(nameof(Settings_Section_Sound));
internal static string Settings_Section_Language => Get(nameof(Settings_Section_Language));
internal static string Settings_Section_Performance => Get(nameof(Settings_Section_Performance));
internal static string Settings_Section_Sound_TabsHint => Get(nameof(Settings_Section_Sound_TabsHint));
// v1.5.6: Chat tab collapsible section titles (R6)
// v1.5.6: Chat tab collapsible section titles
internal static string Settings_Section_Messages => Get(nameof(Settings_Section_Messages));
internal static string Settings_Section_InputPreview => Get(nameof(Settings_Section_InputPreview));
internal static string Settings_Section_AutoTellTabs => Get(nameof(Settings_Section_AutoTellTabs));
internal static string Settings_Section_Emotes => Get(nameof(Settings_Section_Emotes));
internal static string Settings_Section_LinksTooltips => Get(nameof(Settings_Section_LinksTooltips));
internal static string Settings_Section_NoviceNetwork => Get(nameof(Settings_Section_NoviceNetwork));
// v1.5.6: Appearance tab collapsible section titles (R6)
// v1.5.6: Appearance tab collapsible section titles
internal static string Settings_Section_Theme => Get(nameof(Settings_Section_Theme));
internal static string Settings_Section_Fonts => Get(nameof(Settings_Section_Fonts));
internal static string Settings_Section_Colours => Get(nameof(Settings_Section_Colours));
@@ -484,12 +557,12 @@ internal class HellionStrings
internal static string Settings_Section_Timestamps => Get(nameof(Settings_Section_Timestamps));
internal static string Settings_Section_Animations => Get(nameof(Settings_Section_Animations));
// v1.5.6: Window tab collapsible section titles (R6)
// v1.5.6: Window tab collapsible section titles
internal static string Settings_Section_Hide => Get(nameof(Settings_Section_Hide));
internal static string Settings_Section_InactivityHide => Get(nameof(Settings_Section_InactivityHide));
internal static string Settings_Section_Frame => Get(nameof(Settings_Section_Frame));
// v1.5.6: Tabs tab per-tab-item sub-section titles (R6)
// v1.5.6: Tabs tab per-tab-item sub-section titles
internal static string Settings_Section_Tab_Channels => Get(nameof(Settings_Section_Tab_Channels));
internal static string Settings_Section_Tab_Display => Get(nameof(Settings_Section_Tab_Display));
internal static string Settings_Section_Tab_Notification => Get(nameof(Settings_Section_Tab_Notification));
@@ -497,7 +570,7 @@ internal class HellionStrings
internal static string Settings_Section_Tab_PopOut => Get(nameof(Settings_Section_Tab_PopOut));
internal static string Settings_Section_Tab_Volume_AllTabsHint => Get(nameof(Settings_Section_Tab_Volume_AllTabsHint));
// v1.5.6: About tab collapsible section titles (R6)
// v1.5.6: About tab collapsible section titles
internal static string Settings_Section_Extensions => Get(nameof(Settings_Section_Extensions));
internal static string Settings_Section_PluginInfo => Get(nameof(Settings_Section_PluginInfo));
internal static string Settings_Section_Project => Get(nameof(Settings_Section_Project));
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Xarxa de seguretat per als ChatTypes que afegiran futures actualitzacions de FFXIV que el plugin encara no coneix. Per defecte és DESACTIVAT (minimització de dades). Activa-ho si vols que els canals futurs també es registrin completament.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Aplica el filtre a la base de dades existent</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>El filtre de privadesa només afecta els missatges nous. La neteja de sota et permet eliminar retroactivament els missatges ja emmagatzemats que no coincideixen amb la teva llista blanca desada.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>La neteja utilitza la teva llista blanca DESADA (Plugin.Config), no els canvis sense desar de dalt. Fes clic a Desa primer si vols que s'apliquin els canvis actuals.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>L'execució manual utilitza la teva política de retenció DESADA, no els valors dels controls de dalt. Fes clic a Desa primer si vols que l'execució apliqui els canvis actuals.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>La previsualització ha quedat obsoleta: la teva llista blanca ha canviat des de l'última actualització. Fes clic a Actualitza per recalcular.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Aplica la retenció ara</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Maj: Executa la neteja de retenció immediatament amb la política DESADA. Desa els canvis primer.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>La neteja de retenció s'està executant en segon pla…</value>
</data>
@@ -184,7 +172,7 @@
<value>Tria un perfil inicial. Podràs ajustar-ho tot més tard a Configuració → Privadesa.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Minimització de dades (recomanat)</value>
<value>Minimització de dades</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Només es guarden les teves pròpies converses: tells, party, FC, linkshells, cross-world linkshells, alliance i ExtraChat. El xat públic, els diàlegs dels PNJ i el correu brossa del sistema es descarten al nivell d'emmagatzematge. La retenció segueix els valors per defecte de l'especificació (tells 365 dies, canals de conversa propis 90 dies).</value>
@@ -226,7 +214,13 @@
<value>Benvingut a Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Un fork de Chat 2 de Hellion Forge amb valors per defecte respectuosos amb la privadesa, visuals coherents amb la marca i alguns retocs de qualitat de vida.</value>
<value>La teva finestra de xat, de Hellion Forge. Privadesa des del primer moment, en 25 idiomes, i l'organitzes com vulguis.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat va començar com un fork de Chat 2. Des d'aleshores tots dos s'han allunyat prou perquè les bases de codi ja no siguin compatibles.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Els plugins són una zona grisa a Final Fantasy XIV: les condicions d'ús de Square Enix no els cobreixen, i Naoki Yoshida ha demanat públicament que no se'n faci publicitat. Mantén, doncs, el tema fora de Say, Yell, Shout i de qualsevol altre canal públic.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Tres passos ràpids. Podràs canviar-ho tot més tard a Configuració → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Què es guarda?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = recomanat per a la majoria de jugadors.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Recomanat</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Visual</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Carrega la sessió anterior en iniciar</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Aplica els filtres als missatges de sessions anteriors</value>
</data>
@@ -313,14 +304,11 @@
<value>(sense canvis)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Prova-ho: escriu /tell &lt;Nom del jugador&gt; al xat. Hellion Chat obre una pestanya dedicada per a la conversa i precarrega els últims {0} missatges.</value>
<value>Prova-ho: escriu /tell &lt;Nom del jugador&gt; al xat. Hellion Chat obre una pestanya dedicada per a la conversa i precarrega els últims {0} missatges.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Configuració → Hellion Chat per ajustar-ho més tard</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Exportació (RGPD Art. 15 — Dret d'accés)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Exporta els missatges emmagatzemats en format Markdown, JSON o CSV. Això et permet respondre una sol·licitud d'accés d'una persona els missatges de la qual has guardat, o bé endur-te el teu propi historial.</value>
</data>
@@ -457,7 +445,7 @@
<value>Traductors de la comunitat de Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Tells actius</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Desfixa la pestanya</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Converteix en pestanya permanent</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Converteix aquest TempTell en una pestanya normal. L'enllaç del tell amb el company es perd: la pestanya capturarà missatges pels seus filtres de canal a partir d'ara. Per a "la pestanya sobreviu al reconnectar mentre continua lligada a aquest company", utilitza Fixa la pestanya.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Les pestanyes fixades sobreviuen al reconnectar i continuen lligades a aquest interlocutor.</value>
</data>
@@ -504,7 +486,7 @@
<value>Fixada: sobreviu al reconnectar.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Nota: Si XIV Messenger o un plugin similar suprimeix els tells, desactiva l'opció "Suppress DMs" allà perquè Hellion Chat pugui rebre tells i obrir les pestanyes automàtiques.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Historial de tells a les pestanyes automàtiques</value>
</data>
@@ -559,15 +541,9 @@
<value>Només té efecte quan les pestanyes auto-tell estan activades a la pestanya Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Configuració reestructurada</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 ha reestructurat la configuració en pestanyes temàtiques. La teva base de dades de xat i l'historial de missatges no han canviat. La configuració s'ha restablert als valors per defecte. Si vols tornar a seleccionar el teu perfil de privadesa, el botó Reobre es troba a la pestanya Privadesa. Una còpia de seguretat de la configuració anterior es troba a HellionChat.json.pre-v10-backup al costat del fitxer de configuració actiu.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>General</value>
</data>
@@ -590,9 +566,9 @@
<value>Quant a</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Marques de temps</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Marc de la finestra</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Mostra el botó del selector de símbols al costat de l'entrada del xat</value>
</data>
@@ -621,23 +597,17 @@
<value>Afegeix un petit botó a l'esquerra de l'indicador de canal que obre una finestra emergent amb les icones de FFXIV i una llista de símbols seleccionada. Desactiva-ho si prefereixes una barra d'entrada més senzilla.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Emmagatzematge</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Visió general</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Manteniment</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Sistema</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Si fas servir diverses linkshells, el mantenidor recomana una pestanya per shell per tenir una visió general més neta. Duplica la pestanya i restringeix la selecció de canal en cada còpia.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Icona de la pestanya</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Mou la finestra del xat i totes les finestres emergents actives de tornada a la cantonada superior esquerra del monitor principal. Útil quan una finestra ha acabat fora de l'àrea visible després d'un canvi de disposició de pantalla (monitor desconnectat, resolució canviada). El plugin també fa una comprovació automàtica dels límits un cop per sessió; aquest botó és la sortida manual d'emergència si alguna cosa queda inaccessible de totes maneres.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Novetat a v0.6.0: ara pots escriure directament a les finestres emergents. Activa el commutador principal a la configuració de Finestra.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Entesos</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Obre la configuració de finestra</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Pots obrir qualsevol pestanya del xat com a finestra pròpia. Fes clic a la icona de finestra a la part superior dreta o fes clic dret sobre la pestanya. Novetat a v0.6.1: l'entrada a les finestres emergents està activa per defecte (es pot desactivar a Configuració → Finestra).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Entesos</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Obre la configuració</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat no pot iniciar-se mentre Chat 2 estigui carregat.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Desactiva Chat 2 a /xlplugins i torna a activar Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>General</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Idioma, entrada, àudio i rendiment.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Aparença</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Opacitat de la finestra, fonts, moviment</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Tria un theme o importa el teu propi</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Finestra</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Quan la finestra és visible i si es pot moure.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Xat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, previsualització, comportament dels missatges i emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Pestanyes</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Crea i configura pestanyes de xat personalitzades.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Base de dades</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Emmagatzematge, migració, neteja de dades antigues</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Quant a</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Extensions, versió, informació del projecte, traductors i changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Conserva</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Privadesa primer</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Obert</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Dades i privadesa</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Filtre de privadesa, retenció, neteja, exportació i estadístiques de la base de dades.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Avançat (Maj+clic per obrir)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 ha reorganitzat el menú de configuració i ha eliminat l'antiga opció "Substitueix l'estil" (substituïda pel sistema de themes des de la versió 1.1.0). La resta de la configuració no ha canviat. La transparència de la finestra s'ha migrat a "Theme &amp; Layout". Una còpia de seguretat de la configuració anterior es troba a pluginConfigs/HellionChat.json.pre-v16-backup al costat del HellionChat.json actiu.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Les integracions de plugins permeten que HellionChat funcioni conjuntament amb altres plugins de Dalamud instal·lats. Cada integració detecta automàticament el seu objectiu i es desactiva silenciosament quan el plugin objectiu no és present.</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Entrada</value>
</data>
@@ -999,9 +897,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Pestanyes de tell automàtic</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Enllaços i consells</value>
</data>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Aquest missatge conté símbols exclusius del connector que altres jugadors poden veure com a quadres buits. Prem Retorn de nou per enviar-lo igualment.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Insereix un símbol</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Configuració</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Amaga el xat (Retorn per recuperar-lo)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Retorna aquesta pestanya a la finestra principal</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Hi ha una altra operació de base de dades en curs: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>neteja de retenció</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>exportació</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>neteja</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>esborrat de l'historial</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>El filtre de privadesa està desactivat, així que es desa cada canal i res de la base de dades no contradiu la teva configuració. Activa el filtre i tria els canals primer.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>No hi ha cap canal seleccionat, així que una neteja esborraria tot l'historial. Tria els canals que vols conservar, o fes servir el botó d'esborrar si de debò ho vols eliminar tot.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Hi ha {0:N0} missatges desats. Si vols conservar-ne una còpia, exporta'ls abans d'esborrar.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Maj: executa la neteja de retenció ara mateix en comptes d'esperar el pas diari. Esborra els missatges més antics que els límits de dalt.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>No s'ha pogut esborrar l'historial. No s'ha eliminat res, consulta /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetria</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>No es recull cap telemetria. El complement no envia res sobre tu ni sobre el teu ús enlloc.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Traducció automàtica</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Vés al missatge més recent</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Insereix la marca del mapa &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Insereix l'objecte enllaçat &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>desactivat</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Comportament</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Dreceres</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Notificacions</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Modes de visualització</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Historial</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Ajuda d'ordres</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Avís de complement</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Mode de disposició</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Opacitat</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Comportament de mida</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Obertura automàtica de tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Barra lateral</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Marca</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Enllaços</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integracions</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Crèdits</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Llicència</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Fes clic a un botó i després prem la combinació de tecles. Esc esborra.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Passa a la pestanya següent</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Passa a la pestanya anterior</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Canviar-ho reconstrueix l'atles de fonts, així que el xat queda en blanc un moment.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>Rellotge de 24 hores</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Mostra l'historial de sessions anteriors</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Desactivat, el registre comença buit cada vegada que s'inicia el joc i només s'omple amb els missatges rebuts a partir d'aleshores.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Costat de l'ajuda d'ordres</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>A quin costat apareix la llista de suggeriments mentre escrius.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Mode d'obertura automàtica de tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>On s'obre un tell quan arriba.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Canvia a la pestanya a cada tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Altrament la pestanya s'obre en segon pla després de la primera.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Barra lateral</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Pestanyes superiors</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Ubicació de les pestanyes</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>On es col·loca la llista de pestanyes a la finestra principal.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Mostra la barra de títol</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Barra de títol als pop-outs</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Permet moure</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Permet redimensionar</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Llindar de canvi automàtic de la barra lateral</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Per sota d'aquesta amplada la barra lateral es plega en pestanyes superiors, en píxels.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Posició de la vista prèvia</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Mostra la vista prèvia només en escriure</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Repositori Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifest del repositori personalitzat</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Tema actiu: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Bifurca i edita</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Els temes integrats no es poden editar directament. La bifurcació en crea una còpia personalitzada que pots editar i desar.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Edita el tema</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>S'està editant: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Superfícies</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Vores</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Text</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identitat</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Estat</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Desa</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Cancel·la</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Restableix a l'original</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>No es pot restablir mentre s'edita una bifurcació. Desa o cancel·la primer.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Desa o descarta primer els teus canvis</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Personalitzats ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Bifurca el tema actiu</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importa un fitxer de tema…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Ruta al fitxer JSON (o arrossega'l a la carpeta)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Exporta el tema</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Freds</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturals</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Clàssics</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (inclosa)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Tipus de lletra del joc</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Global: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Actiu: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Escriu un missatge...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplica</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>vista prèvia</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>manteniment</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} pestanya</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} pestanyes</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} xiuxiueig</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} xiuxiueigs</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} msg</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k msg</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Campió» Vista prèvia</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>obert</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Sessió no iniciada</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Més accions</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Záchranná síť pro ChatTypes přidané budoucími patchemi FFXIV, které plugin ještě nezná. Výchozí stav je VYPNUTO (minimalizace dat). Zapni, pokud chceš, aby se budoucí kanály také plně logovaly.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Použít filtr na existující databázi</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Filtr soukromí ovlivňuje jen nové zprávy. Čištění níže ti umožní zpětně odstranit již uložené zprávy, které neodpovídají tvé uložené whitelistě.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Čištění používá tvoji ULOŽENOU whitelistu (Plugin.Config), ne neuložené změny výše. Klikni nejdřív na Uložit, chceš-li použít aktuální změny.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Ruční spuštění používá tvoji ULOŽENOU zásadu uchovávání, ne hodnoty posuvníků výše. Klikni nejdřív na Uložit, chceš-li použít aktuální změny.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Náhled je zastaralý: tvoje whitelist se od posledního obnovení změnila. Klikni na Obnovit a přepočítej.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Použít uchovávání nyní</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Spustí čištění uchovávání okamžitě podle ULOŽENÉ zásady. Nejdřív ulož změny.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Čištění uchovávání běží na pozadí…</value>
</data>
@@ -184,7 +172,7 @@
<value>Vyber si výchozí profil. Vše můžeš kdykoli později upravit v Nastavení → Soukromí.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Minimalizace dat (doporučeno)</value>
<value>Minimalizace dat</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Ukládají se pouze tvoje vlastní konverzace: telly, party, FC, linkshelly, cross-world linkshelly, aliance a ExtraChat. Veřejný chat, dialogy NPC a systémový spam se na úrovni úložiště zahodí. Uchovávání dle výchozích hodnot specifikace (telly 365 dní, vlastní konverzační kanály 90 dní).</value>
@@ -226,7 +214,13 @@
<value>Vítej v Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Fork Chat 2 od Hellion Forge s výchozím nastavením ohleduplným ke soukromí, vizuálem odpovídajícím značce a pár vylepšeními kvality života.</value>
<value>Tvoje okno chatu od Hellion Forge. Soukromí od prvního spuštění, 25 jazyků a rozvržení si nastavíš sám.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat vznikl jako fork Chat 2. Od té doby se oba projekty rozešly natolik, že jejich kódové základny už nejsou kompatibilní.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Pluginy jsou ve Final Fantasy XIV šedá zóna: podmínky užívání Square Enix je nepokrývají a Naoki Yoshida veřejně požádal, aby se nepropagovaly. Nezmiňuj proto toto téma na Say, Yell, Shout ani na žádném jiném veřejném kanálu.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Tři krátké kroky. Vše můžeš kdykoli změnit v Nastavení → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Co se bude ukládat?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = doporučeno pro většinu hráčů.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Doporučeno</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Vzhled</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Načíst předchozí relaci při spuštění</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Použít filtry na zprávy z předchozích relací</value>
</data>
@@ -313,14 +304,11 @@
<value>(beze změny)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Vyzkoušej: napiš /tell &lt;Jméno hráče&gt; do chatu. Hellion Chat automaticky otevře vlastní záložku pro konverzaci a přednačte posledních {0} zpráv.</value>
<value>Vyzkoušej: napiš /tell &lt;Jméno hráče&gt; do chatu. Hellion Chat automaticky otevře vlastní záložku pro konverzaci a přednačte posledních {0} zpráv.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Nastavení → Hellion Chat pro pozdější doladění</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Export (GDPR Art. 15 — Právo na přístup)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Exportuj uložené zprávy jako Markdown, JSON nebo CSV. Umožňuje ti splnit žádost o přístup od osoby, jejíž zprávy uchováváš, nebo vzít s sebou vlastní historii.</value>
</data>
@@ -457,7 +445,7 @@
<value>Komunitní překladatelé Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Aktivní telly</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Odepnout záložku</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Povýšit na trvalou záložku</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Přemění tento TempTell na normální záložku. Vazba na partnera přes tell se zruší: záložka od té doby zachytává zprávy podle filtrů kanálů. Chceš-li „záložka přežije relog a zůstane svázaná s tímto partnerem", použij raději Připnout záložku.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Připnuté záložky přeživají relog a zůstávají svázané s tímto konverzačním partnerem.</value>
</data>
@@ -504,7 +486,7 @@
<value>Připnuto: přežívá relog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Poznámka: Pokud XIV Messenger nebo podobný plugin potlačuje telly, deaktivuj tam možnost „Suppress DMs", aby Hellion Chat mohl přijímat telly a otevírat auto-záložky.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Historie tellů v auto-záložkách</value>
</data>
@@ -559,15 +541,9 @@
<value>Funguje pouze tehdy, jsou-li auto-tell záložky zapnuty v záložce Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Nastavení bylo přestrukturováno</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 přestrukturoval nastavení do tematických záložek. Tvoje databáze chatu a historie zpráv zůstávají beze změny. Nastavení bylo resetováno na výchozí hodnoty. Chceš-li znovu vybrat profil soukromí, tlačítko Znovu otevřít je v záložce Soukromí. Záloha předchozí konfigurace se nachází v HellionChat.json.pre-v10-backup vedle aktivního konfiguračního souboru.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Obecné</value>
</data>
@@ -590,9 +566,9 @@
<value>O pluginu</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Časová razítka</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Rám okna</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Zobrazit tlačítko pro výběr symbolů vedle chatového vstupu</value>
</data>
@@ -621,23 +597,17 @@
<value>Přidá malé tlačítko vlevo od indikátoru kanálu, které otevře popup s ikonami FFXIV a kurátovaným seznamem symbolů. Vypni, chceš-li mít čistší vstupní lištu.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Úložiště</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Přehled</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Údržba</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Systém</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emoty</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Pokud používáš více linkshellů, maintainer doporučuje mít jednu záložku na shell pro přehlednější zobrazení. Zduplikuj záložku a v každé kopii omezte výběr kanálů.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Ikona záložky</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Přesune okno chatu a všechna aktivní pop-out okna zpět do levého horního rohu primárního monitoru. Užitečné, když se okno po změně rozvržení displeje ocitlo mimo viditelnou oblast (monitor odpojen, změněné rozlišení). Plugin také jednou za relaci provádí automatickou kontrolu hranic. Toto tlačítko je ruční záchranný východ, pokud přesto něco zůstane nedostupné.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Novinka ve v0.6.0: Teď můžeš psát přímo v pop-outech. Zapni hlavní přepínač v nastavení okna.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Rozumím</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Otevřít nastavení okna</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Libovolnou chat záložku můžeš otevřít jako vlastní okno. Klikni na ikonu okna vpravo nahoře nebo pravým tlačítkem klikni na záložku. Novinka ve v0.6.1: vstup v pop-outu je ve výchozím nastavení aktivní (lze vypnout v Nastavení → Okno).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Rozumím</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Otevřít nastavení</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat se nemůže spustit, dokud je načten Chat 2.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Deaktivuj Chat 2 v /xlplugins a poté znovu aktivuj Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Obecné</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Jazyk, vstup, zvuk a výkon.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Vzhled</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Průhlednost okna, písma, animace</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Vyber theme nebo importuj vlastní</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Okno</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Kdy je okno viditelné a zda se dá přesouvat.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Telly, náhled, chování zpráv a emoty.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Záložky</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Vytvárej a konfiguruj vlastní chat záložky.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Databáze</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Úložiště, migrace, staré čištění</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>O pluginu</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Rozšíření, verze, informace o projektu, překladatelé a changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Ponechat</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Soukromí především</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Otevřeno</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Data a soukromí</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Filtr soukromí, uchovávání, čištění, export a statistiky databáze.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Pokročilé (Shift+klik pro otevření)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 přeorganizoval nabídku nastavení a odstranil starou možnost „Override style" (nahrazenou systémem themes od verze 1.1.0). Zbývající nastavení zůstávají nezměněna. Průhlednost okna byla přesunuta do „Theme &amp; Layout". Záloha předchozí konfigurace se nachází v pluginConfigs/HellionChat.json.pre-v16-backup vedle aktivního HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Integrace pluginů umožňují HellionChat spolupracovat s ostatními nainstalovanými Dalamud pluginy. Každá integrace automaticky detekuje svůj cíl a tiše se deaktivuje, když cílový plugin chybí.</value>
</data>
@@ -955,7 +853,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Vstup</value>
</data>
@@ -998,9 +896,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Automatické karty pro tell</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emoty</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Odkazy a popisky</value>
</data>
@@ -1145,4 +1040,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Tato zpráva obsahuje symboly pouze pro plugin, které ostatní hráči mohou vidět jako prázdné čtverce. Stiskni Enter znovu pro odeslání.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Vložit symbol</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Nastavení</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Skrýt chat (Enter jej vrátí)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Vrátit tuto kartu do hlavního okna</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Právě probíhá jiná operace s databází: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>úklid podle doby uchování</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>export</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>úklid</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>mazání historie</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Filtr soukromí je vypnutý, takže se ukládá každý kanál a nic v databázi neodporuje tvému nastavení. Nejdřív filtr zapni a vyber kanály.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Není vybraný žádný kanál, takže úklid by smazal celou historii. Vyber kanály, které chceš zachovat, nebo použij tlačítko pro vymazání, pokud opravdu chceš smazat vše.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Uloženo je {0:N0} zpráv. Pokud si chceš ponechat kopii, před vymazáním je exportuj.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: spustí úklid podle doby uchování hned, místo čekání na denní běh. Smaže zprávy starší než limity výše.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Vymazání historie selhalo. Nic nebylo odstraněno, viz /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetrie</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Nesbírá se žádná telemetrie. Plugin nikam neposílá nic o tobě ani o tvém používání.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Automatický překlad</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Přejít na nejnovější zprávu</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Vložit značku mapy &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Vložit odkázaný předmět &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>vypnuto</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Chování</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Klávesové zkratky</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Oznámení</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Režimy zobrazení</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Historie</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Nápověda k příkazům</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Upozornění na plugin</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Režim rozvržení</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Neprůhlednost</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Chování při změně velikosti</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Automatické otevření tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Postranní panel</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Značka</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Odkazy</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrace</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Poděkování</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licence</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Klikni na tlačítko a poté stiskni kombinaci kláves. Esc smaže.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Přepnout na další záložku</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Přepnout na předchozí záložku</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Přepnutí přestaví atlas písem, takže chat na okamžik zmizí.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24hodinový formát</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Zobrazit historii z předchozích relací</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Vypnuto znamená, že se protokol při každém spuštění hry začíná prázdný a plní se jen zprávami přijatými od té chvíle.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Strana nápovědy k příkazům</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Na které straně se během psaní zobrazuje seznam nápověd.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Režim automatického otevření tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Kde se tell otevře, když dorazí.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Přepnout na kartu při každém tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Jinak se záložka po první zprávě otevře na pozadí.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Postranní panel</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Horní záložky</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Umístění záložek</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Kde v hlavním okně sedí seznam záložek.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Zobrazit záhlaví</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Záhlaví u pop-out oken</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Povolit přesouvání</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Povolit změnu velikosti</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Práh automatického přepnutí postranního panelu</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Pod touto šířkou se postranní panel složí do horních záložek, v pixelech.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Umístění náhledu</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Zobrazit náhled jen při psaní</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Repozitář Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifest vlastního repozitáře</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Aktivní motiv: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Rozvětvit a upravit</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Vestavěné motivy nelze upravovat přímo. Rozvětvení vytvoří vlastní kopii, kterou můžeš upravit a uložit.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Upravit motiv</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Upravuje se: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Plochy</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Okraje</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Text</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identita</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Stav</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Uložit</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Zrušit</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Obnovit podle zdroje</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Při úpravě rozvětvení nelze obnovit. Nejdřív ulož nebo zruš.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Nejdřív ulož nebo zahoď své změny</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Vlastní ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Rozvětvit aktivní motiv</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importovat soubor motivu…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Cesta k souboru JSON (nebo přetáhni do složky)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Exportovat motiv</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Chladné</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Přírodní</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Klasické</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (v balíčku)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Herní písmo</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Globální: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Aktivní: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Napiš zprávu...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplikovat</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>náhled</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>údržba</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} karta</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} karty</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} šeptání</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} šeptání</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} zpr.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k zpr.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Šampion» Náhled</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>otevřeno</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Nepřihlášen</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Další akce</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Sikkerhedsnet for ChatTypes tilføjet af fremtidige FFXIV-opdateringer, som plugin'et endnu ikke kender. Standard er FRA (dataminimering). Aktivér hvis du også vil have fremtidige kanaler logget fuldt ud.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Anvend filter på eksisterende database</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Privatlivsfilteret påvirker kun nye beskeder. Oprydningen nedenfor lader dig bagudrettet fjerne allerede gemte beskeder, der ikke matcher din gemte hvidliste.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Oprydningen bruger din GEMTE hvidliste (Plugin.Config), ikke ugemte ændringer ovenfor. Klik Gem først, hvis du vil anvende dine aktuelle ændringer.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Den manuelle kørsel bruger din GEMTE opbevaringspolitik, ikke skyderknapværdierne ovenfor. Klik Gem først, hvis kørslen skal anvende dine aktuelle ændringer.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Forhåndsvisning er forældet: din hvidliste er ændret siden sidste opdatering. Klik Opdater for at genberegne.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Anvend opbevaring nu</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Kører oprydningen med den GEMTE politik med det samme. Gem dine ændringer først.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Opbevaringsoprydning kører i baggrunden…</value>
</data>
@@ -184,7 +172,7 @@
<value>Vælg en startprofil. Du kan justere alt efterfølgende under Indstillinger → Privatliv.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Dataminimering (anbefalet)</value>
<value>Dataminimering</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Kun dine egne samtaler gemmes: tells, gruppe, FC, linkshells, cross-world linkshells, alliance og ExtraChat. Offentlig chat, NPC-dialoger og systemstøj kasseres på lagerniveau. Opbevaring følger spec-standarder (tells 365 dage, egne samtalekanaler 90 dage).</value>
@@ -226,7 +214,13 @@
<value>Velkommen til Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>En Chat 2 fork fra Hellion Forge med privatlivsbevidste standarder, brandkonsistent udseende og et par praktiske forbedringer.</value>
<value>Dit chatvindue fra Hellion Forge. Privatliv fra første start, 25 sprog, og du sætter det op, som du vil.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat startede som en fork af Chat 2. De to har siden fjernet sig så meget fra hinanden, at kodebaserne ikke længere er kompatible.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Plugins er en gråzone i Final Fantasy XIV: Square Enix' brugsvilkår dækker dem ikke, og Naoki Yoshida har offentligt bedt om, at man ikke reklamerer for dem. Hold derfor emnet ude af Say, Yell, Shout og alle andre offentlige kanaler.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Tre korte trin. Du kan ændre alt efterfølgende under Indstillinger → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Hvad gemmes?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = anbefalet til de fleste spillere.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Anbefalet</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Udseende</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Indlæs forrige session ved opstart</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Anvend filtre på beskeder fra tidligere sessioner</value>
</data>
@@ -313,14 +304,11 @@
<value>(uændret)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Prøv det: skriv /tell &lt;Spillernavn&gt; i chatten. Hellion Chat åbner en dedikeret tab til samtalen og forudindlæser de sidste {0} beskeder.</value>
<value>Prøv det: skriv /tell &lt;Spillernavn&gt; i chatten. Hellion Chat åbner en dedikeret tab til samtalen og forudindlæser de sidste {0} beskeder.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Indstillinger → Hellion Chat for at finjustere senere</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Eksport (GDPR Art. 15 — Ret til indsigt)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Eksportér gemte beskeder som Markdown, JSON eller CSV. Det lader dig opfylde en indsigtsanmodning fra en person, hvis beskeder du har gemt, eller tage din egen historik med.</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 community-oversættere (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Aktive tells</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Frigør tab</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Konvertér til permanent tab</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Gør denne TempTell til en regulær tab. Tell-bindingen til samtalepartneren fjernes, og tab'en vil fremover opfange beskeder via dens kanalfiltre. Brug Fastgør tab i stedet, hvis du vil have "tab overlever genlog og forbliver bundet til denne partner".</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Fastgjorte tabs overlever genlog og forbliver bundet til denne samtalepartner.</value>
</data>
@@ -504,7 +486,7 @@
<value>Fastgjort: overlever genlog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Bemærk: Hvis XIV Messenger eller et lignende plugin undertrykker tells, skal du deaktivere indstillingen "Suppress DMs" der, så Hellion Chat kan modtage tells og åbne auto-tabs.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Tell-historik i auto-tabs</value>
</data>
@@ -559,15 +541,9 @@
<value>Træder kun i kraft når auto-tell-tabs er aktiveret under fanen Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Indstillinger omstruktureret</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 har omstruktureret indstillingerne i tematiske faner. Din chat-database og beskedhistorik er uændret. Indstillinger er nulstillet til standarder. Hvis du vil vælge din privatlivsprofil på ny, finder du Genåbn-knappen under fanen Privatliv. En sikkerhedskopi af den forrige konfiguration ligger ved siden af den aktive konfigurationsfil som HellionChat.json.pre-v10-backup.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Generelt</value>
</data>
@@ -590,9 +566,9 @@
<value>Om</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Tidsstempler</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Vinduesramme</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Vis symbolvælger-knap ved siden af chat-input</value>
</data>
@@ -621,23 +597,17 @@
<value>Tilføjer en lille knap til venstre for kanalindikatoren, der åbner et popup med FFXIV-ikoner og en udvalgt symbolliste. Deaktivér for en slankere inputlinje.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Lagring</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Oversigt</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Vedligeholdelse</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>System</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Bruger du flere linkshells, anbefaler vedligeholderen én tab pr. shell for et bedre overblik. Dupliker tab'en og begræns kanalvalget i hver kopi.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Tab-ikon</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Flytter chat-vinduet og alle aktive pop-outs tilbage til øverste venstre hjørne af den primære skærm. Nyttigt når et vindue er havnet uden for det synlige område efter en skærmlayoutændring (skærm frakoblet, opløsning ændret). Plugin'et udfører også et automatisk bounds-check én gang pr. session. Denne knap er den manuelle nødudgang, hvis noget alligevel ender utilgængeligt.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Nyt i v0.6.0: Du kan nu skrive direkte i pop-outs. Aktivér masterknappen under Vinduesindstillinger.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Forstået</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Åbn vinduesindstillinger</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Du kan åbne enhver chat-tab som sit eget vindue. Klik på vindues-ikonet øverst til højre, eller højreklik på tab'en. Nyt i v0.6.1: pop-out-input er aktiv som standard (kan deaktiveres under Indstillinger → Vindue).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Forstået</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Åbn indstillinger</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat kan ikke starte mens Chat 2 er indlæst.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Deaktivér Chat 2 i /xlplugins, og aktivér derefter Hellion Chat igen.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Generelt</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Sprog, input, lyd og ydeevne.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Udseende</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Vindues-opacitet, skrifttyper, bevægelse</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Vælg et theme eller importér dit eget</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Vindue</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Hvornår vinduet er synligt, og om det kan flyttes.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, forhåndsvisning, beskedadfærd og emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Tabs</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Opret og konfigurér brugerdefinerede chat-tabs.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Database</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Lagring, migration, gammel oprydning</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Om</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Udvidelser, version, projektoplysninger, oversættere og changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Behold</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Privatliv først</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Åben</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Data og privatliv</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Privatlivsfilter, opbevaring, oprydning, eksport og databasestatistik.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Avanceret (Shift+klik for at åbne)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 har omorganiseret indstillingsmenuen og fjernet den gamle "Tilsidesæt stil"-indstilling (erstattet af theme-systemet fra 1.1.0). Dine øvrige indstillinger er uændret. Vinduesgennemsigtighed er migreret til "Theme &amp; Layout". En sikkerhedskopi af den forrige konfiguration ligger ved siden af den aktive HellionChat.json som pluginConfigs/HellionChat.json.pre-v16-backup.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Plugin-integrationer lader HellionChat arbejde sammen med andre installerede Dalamud-plugins. Hver integration registrerer automatisk sit mål og deaktiverer sig stille, når målplugin'et mangler.</value>
</data>
@@ -955,7 +853,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Input</value>
</data>
@@ -998,9 +896,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Auto-tell-faner</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Links og værktøjstip</value>
</data>
@@ -1145,4 +1040,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Denne besked indeholder plugin-kun symboler, som andre spillere muligvis ser som tomme bokse. Tryk Enter igen for at sende alligevel.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Indsæt symbol</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Indstillinger</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Skjul chat (Enter henter den tilbage)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Send denne fane tilbage til hovedvinduet</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>En anden databasehandling kører: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>oprydning efter opbevaringsregler</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>eksport</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>oprydning</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>sletning af historikken</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Privatlivsfilteret er slået fra, så alle kanaler gemmes, og intet i databasen strider mod dine indstillinger. Slå filteret til, og vælg kanaler først.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Ingen kanal er valgt, så en oprydning ville slette hele historikken. Vælg de kanaler, du vil beholde, eller brug sletteknappen, hvis du virkelig vil af med alt.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Der er gemt {0:N0} beskeder. Vil du beholde en kopi, så eksportér dem før du sletter.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: kører oprydningen med det samme i stedet for at vente på det daglige gennemløb. Sletter beskeder ældre end grænserne ovenfor.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Sletning af historikken mislykkedes. Intet blev fjernet, se /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetri</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Der indsamles ingen telemetri. Pluginet sender intet om dig eller din brug nogen steder.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Auto-oversættelse</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Hop til den seneste besked</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Indsæt kortmarkering &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Indsæt linket genstand &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>fra</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Adfærd</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Tastaturgenveje</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Notifikationer</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Visningstilstande</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Historik</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Kommandohjælp</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Plugin-oplysning</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Layouttilstand</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Uigennemsigtighed</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Størrelsesændring</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Automatisk åbning af tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Sidepanel</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Varemærke</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Links</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrationer</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Krediteringer</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licens</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Klik på en knap, og tryk derefter tastekombinationen. Esc rydder.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Skift til næste tab</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Skift til forrige tab</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Skift genopbygger fontatlasset, så chatten er tom et øjeblik.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24-timers ur</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Vis historik fra tidligere sessioner</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Slået fra starter loggen tom, hver gang spillet startes, og fyldes kun med beskeder modtaget derefter.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Side for kommandohjælp</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Hvilken side listen med kommandotips vises på, mens du skriver.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Tilstand for automatisk åbning af tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Hvor en tell åbnes, når den ankommer.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Skift til tab ved hver tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Ellers åbnes tab'en i baggrunden efter den første.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Sidepanel</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Tabs øverst</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Placering af tabs</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Hvor tab-listen sidder i hovedvinduet.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Vis titellinje</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Vis titellinje for pop-out-vinduer</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Tillad flytning</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Tillad størrelsesændring</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Grænse for automatisk skift af sidepanel</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Under denne bredde folder sidepanelet sig til tabs øverst, i pixels.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Placering af forhåndsvisning</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Vis kun forhåndsvisning under skrivning</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea-repositorium</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifest for brugerdefineret repo</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Aktivt tema: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Forgren og rediger</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Indbyggede temaer kan ikke redigeres direkte. Forgrening laver en brugerdefineret kopi, du kan redigere og gemme.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Rediger tema</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Redigerer: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Flader</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Kanter</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Tekst</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identitet</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Status</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Gem</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Annuller</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Nulstil til kilden</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Nulstilling er ikke muligt, mens du redigerer en forgrening. Gem eller annuller først.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Gem eller kassér dine ændringer først</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Brugerdefinerede ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Forgren aktivt tema</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importér temafil…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Sti til JSON-fil (eller træk-og-slip i mappen)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Eksportér tema</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Kølige</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturlige</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Klassiske</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (medfølger)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Spillets skrifttype</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Global: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Aktiv: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Skriv en besked...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplikér</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>forhåndsvisning</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>vedligeholdelse</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} tab</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} tabs</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} tell</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} tells</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} besk.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k besk.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Champion» Forhåndsvisning</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>åben</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Ikke logget ind</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Flere handlinger</value>
</data>
</root>
+378 -163
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Sicherheitsnetz für ChatTypes, die durch zukünftige FFXIV-Patches dazukommen und dem Plugin noch nicht bekannt sind. Standard ist AUS (Datensparsamkeit). Aktivieren, wenn du auch zukünftige Kanäle vollständig mitloggen willst.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Filter auf bestehende Datenbank anwenden</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Der Datenschutz-Filter wirkt nur auf neue Nachrichten. Über das Aufräumen unten kannst du bereits gespeicherte Nachrichten nachträglich entfernen, die nicht zu deiner gespeicherten Whitelist passen.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Das Aufräumen nutzt deine GESPEICHERTE Whitelist (Plugin.Config), nicht ungespeicherte Änderungen oben. Klicke zuerst Speichern, wenn du deine aktuellen Änderungen anwenden willst.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Der manuelle Lauf nutzt deine GESPEICHERTE Retention-Policy, nicht die Slider-Werte oben. Klicke zuerst Speichern, wenn der Lauf deine aktuellen Änderungen anwenden soll.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Vorschau veraltet, deine Whitelist hat sich seit dem letzten Aktualisieren geändert. Klicke Aktualisieren, um neu zu berechnen.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Aufbewahrung jetzt anwenden</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Strg+Umschalt: Führt die Aufbewahrungs-Bereinigung sofort mit der GESPEICHERTEN Vorgabe aus. Speichere deine Änderungen vorher.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Aufbewahrungs-Bereinigung läuft im Hintergrund…</value>
</data>
@@ -184,10 +172,10 @@
<value>Wähle ein Start-Profil. Du kannst später alles unter Einstellungen → Datenschutz anpassen.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Datensparsamkeit (empfohlen)</value>
<value>Datensparsamkeit</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Es werden nur deine eigenen Konversationen gespeichert: Tells, Gruppe, FC, Linkshells, Cross-World-Linkshells, Allianz und ExtraChat. Öffentlicher Chat, NPC-Dialoge und System-Spam werden auf der Storage-Ebene verworfen. Aufbewahrung nach Spec-Defaults (Tells 365 Tage, eigene Konversations-Kanäle 90 Tage).</value>
<value>Es werden nur deine eigenen Konversationen gespeichert: Flüsternachrichten, Gruppe, FC, Linkshells, Cross-World-Linkshells, Allianz und ExtraChat. Öffentlicher Chat, NPC-Dialoge und System-Spam werden auf der Storage-Ebene verworfen. Aufbewahrung nach Spec-Defaults (Flüsternachrichten 365 Tage, eigene Konversations-Kanäle 90 Tage).</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Apply" xml:space="preserve">
<value>Datensparsamkeit übernehmen</value>
@@ -226,7 +214,13 @@
<value>Willkommen bei Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Ein Chat 2 Fork von Hellion Forge mit DSGVO-konformen Defaults, brand-konsistentem Look und Quality-of-Life-Verbesserungen.</value>
<value>Dein Chat-Fenster von Hellion Forge. Datensparsam ab Werk, in 25 Sprachen, und du richtest es dir ein wie du willst.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Plugins sind in Final Fantasy XIV eine Grauzone: Die Nutzungsbedingungen von Square Enix decken sie nicht ab, und Naoki Yoshida hat öffentlich darum gebeten, nicht damit zu werben. Halte das Thema deshalb aus Sagen, Rufen, Schreien und allen anderen öffentlichen Kanälen heraus.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat ging ursprünglich aus Chat 2 hervor. Beide haben sich seitdem so weit auseinanderentwickelt, dass die Codebasen nicht mehr kompatibel sind.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>3 kurze Schritte. Du kannst alles später unter Einstellungen → Hellion Chat ändern.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Was darf gespeichert werden?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = empfohlen für die meisten Spieler.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Empfohlen</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -268,22 +262,19 @@
<value>Verlauf</value>
</data>
<data name="Wizard_Step3_Section_TellTabs" xml:space="preserve">
<value>Tell-Tabs</value>
<value>Flüster-Tabs</value>
</data>
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Optik</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Vorherige Session beim Start laden</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Filter auch auf alte Messages anwenden</value>
</data>
<data name="Wizard_Step3_AutoTellTabsHistoryPreload_Label" xml:space="preserve">
<value>N Tell-Messages beim Öffnen eines Auto-Tabs vorladen</value>
<value>N Flüsternachrichten beim Öffnen eines Auto-Tabs vorladen</value>
</data>
<data name="Wizard_Step3_UseCompactDensity_Label" xml:space="preserve">
<value>Kompakter Density-Modus</value>
<value>Kompakte Dichte</value>
</data>
<data name="Wizard_Step3_PrettierTimestamps_Label" xml:space="preserve">
<value>Schönere Timestamps (relative Zeit)</value>
@@ -304,7 +295,7 @@
<value>Verlauf: {0}</value>
</data>
<data name="Wizard_Step4_Summary_TellTabs" xml:space="preserve">
<value>Tell-Tabs: {0} Messages vorladen</value>
<value>Flüster-Tabs: {0} Messages vorladen</value>
</data>
<data name="Wizard_Step4_Summary_Visual" xml:space="preserve">
<value>Optik: {0}</value>
@@ -313,14 +304,11 @@
<value>(unverändert)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Probier's aus: Tipp /tell &lt;Spielername&gt; in den Chat. Hellion Chat öffnet automatisch einen eigenen Tab für die Unterhaltung und lädt die letzten {0} Messages mit.</value>
<value>Probier's aus: Tipp /tell &lt;Spielername&gt; in den Chat. Hellion Chat öffnet automatisch einen eigenen Tab für die Unterhaltung und lädt die letzten {0} Messages mit.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Einstellungen → Hellion Chat zum späteren Anpassen</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Export (DSGVO Art. 15 — Auskunftsrecht)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Gespeicherte Nachrichten als Markdown, JSON oder CSV exportieren. Damit kannst du einer Auskunftsanfrage einer Person nachkommen, deren Nachrichten du gespeichert hast, oder deine eigene Historie mitnehmen.</value>
</data>
@@ -457,9 +445,9 @@
<value>Chat-2-Community-Übersetzer (Upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime-Strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Aktive Tells</value>
<value>Aktive Flüsternachrichten</value>
</data>
<data name="AutoTellTabs_HistorySeparator" xml:space="preserve">
<value>— Frühere Unterhaltungen —</value>
@@ -479,20 +467,14 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Tab lösen</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>In Standard-Tab umwandeln</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Wandelt den TempTell in einen regulären Tab um. Die Tell-Bindung an die Person geht verloren, der Tab fängt dann Nachrichten anhand der Channel-Filter ein. Für „Tab überlebt Relog" stattdessen „Tab anpinnen" wählen.</value>
</data>
<data name="PinTab_LimitReached" xml:space="preserve">
<value>Maximal {0} angepinnte Tell-Tabs erreicht. Erst einen lösen oder dauerhaft behalten.</value>
<value>Maximal {0} angepinnte Flüster-Tabs erreicht. Erst einen lösen oder dauerhaft behalten.</value>
</data>
<data name="PinTab_PinnedTooltip" xml:space="preserve">
<value>Angepinnt: überlebt Relog.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Angepinnte Tabs überleben Relog und behalten die Bindung an die Tell-Person.</value>
<value>Angepinnte Tabs überleben Relog und behalten die Bindung an die Flüster-Partner.</value>
</data>
<data name="PinTab_SectionHeader" xml:space="preserve">
<value>Angepinnt</value>
@@ -501,12 +483,12 @@
<value>Sidebar-Breite</value>
</data>
<data name="Settings_ThemeAndLayout_SidebarWidth_Description" xml:space="preserve">
<value>Breite der Tab-Sidebar in Pixeln. Default (44 px) ist Icon-only; breiter machen damit Sektion-Header wie „Aktive Tells (3)" nicht abgeschnitten werden.</value>
<value>Breite der Tab-Sidebar in Pixeln. Default (44 px) ist Icon-only; breiter machen damit Sektion-Header wie „Aktive Flüsternachrichten (3)" nicht abgeschnitten werden.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat-Einstellungstab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
<value>Auto-Flüster-Tabs</value>
</data>
<data name="ChatLog_AutoTellTabs_Enable_Name" xml:space="preserve">
<value>Bei jedem /tell automatisch einen Tab pro Gesprächspartner öffnen</value>
@@ -515,22 +497,22 @@
<value>Sobald du einen /tell empfängst oder sendest, wird automatisch ein temporärer Tab für diesen Spieler geöffnet. Die Tabs verschwinden beim Logout.</value>
</data>
<data name="ChatLog_AutoTellTabs_Limit_Name" xml:space="preserve">
<value>Maximale Anzahl der Auto-Tell-Tabs</value>
<value>Maximale Anzahl der Auto-Flüster-Tabs</value>
</data>
<data name="ChatLog_AutoTellTabs_Limit_Description" xml:space="preserve">
<value>Beim Erreichen werden begrüßte Tabs mit der ältesten Aktivität zuerst geschlossen. Änderungen greifen beim nächsten /tell. Diese Grenze gilt nur für den automatisch verwalteten Pool. Angepinnte Tell-Tabs (Rechtsklick → Tab anpinnen) leben in einem separaten Pool von bis zu 5 Tabs und überleben Relog.</value>
<value>Beim Erreichen werden begrüßte Tabs mit der ältesten Aktivität zuerst geschlossen. Änderungen greifen beim nächsten /tell. Diese Grenze gilt nur für den automatisch verwalteten Pool. Angepinnte Flüster-Tabs (Rechtsklick → Tab anpinnen) leben in einem separaten Pool von bis zu 5 Tabs und überleben Relog.</value>
</data>
<data name="ChatLog_AutoTellTabs_Compact_Name" xml:space="preserve">
<value>Kompakte Anzeige</value>
</data>
<data name="ChatLog_AutoTellTabs_Compact_Description" xml:space="preserve">
<value>Zeigt nur einen dünnen Separator zwischen normalen Tabs und Auto-Tell-Tabs, ohne Sektions-Header.</value>
<value>Zeigt nur einen dünnen Separator zwischen normalen Tabs und Auto-Flüster-Tabs, ohne Sektions-Header.</value>
</data>
<data name="ChatLog_AutoTellTabs_GreetedToggle_Name" xml:space="preserve">
<value>„Als begrüßt markieren"-Button anzeigen</value>
</data>
<data name="ChatLog_AutoTellTabs_GreetedToggle_Description" xml:space="preserve">
<value>Fügt neben jedem Auto-Tell-Tab einen Klick-Button hinzu, um einen Gesprächspartner als bereits begrüßt zu markieren: der Tab-Name wird dann gedimmt. Nützlich für Club-Greeter, die parallel viele Konversationen führen. Standardmäßig aus.</value>
<value>Fügt neben jedem Auto-Flüster-Tab einen Klick-Button hinzu, um einen Gesprächspartner als bereits begrüßt zu markieren: der Tab-Name wird dann gedimmt. Nützlich für Club-Greeter, die parallel viele Konversationen führen. Standardmäßig aus.</value>
</data>
<data name="ChatLog_AutoTellTabs_OpenAsPopout_Name" xml:space="preserve">
<value>Neue /tell-Tabs direkt als Pop-Out öffnen</value>
@@ -539,35 +521,29 @@
<value>Wenn aktiv, wird jeder neu angelegte /tell-Tab sofort als eigenes Fenster geöffnet. Beim Schließen des Fensters kehrt der Tab in die Seitenleiste zurück.</value>
</data>
<data name="ChatLog_AutoTellTabs_PreloadHint" xml:space="preserve">
<value>Die Anzahl der vorgeladenen Tells lässt sich im Datenschutz-Tab einstellen.</value>
<value>Die Anzahl der vorgeladenen Flüsternachrichten lässt sich im Datenschutz-Tab einstellen.</value>
</data>
<data name="ChatLog_AutoTellTabs_ConflictHint" xml:space="preserve">
<value>Hinweis: Falls XIV Messanger oder ein ähnliches Plugin Tells unterdrückt, dort die Option „Suppress DMs" deaktivieren, damit Hellion Chat Tells empfangen und die Auto-Tabs öffnen kann.</value>
<value>Hinweis: Falls XIV Messanger oder ein ähnliches Plugin Flüsternachrichten unterdrückt, dort die Option „Suppress DMs" deaktivieren, damit Hellion Chat Flüsternachrichten empfangen und die Auto-Tabs öffnen kann.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Datenschutz-Einstellungstab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Tell-Verlauf in Auto-Tabs</value>
<value>Flüster-Verlauf in Auto-Tabs</value>
</data>
<data name="Privacy_AutoTellTabs_Preload_Name" xml:space="preserve">
<value>Anzahl der vorgeladenen Tells</value>
<value>Anzahl der vorgeladenen Flüsternachrichten</value>
</data>
<data name="Privacy_AutoTellTabs_Preload_Description" xml:space="preserve">
<value>Wie viele frühere Tell-Nachrichten beim Öffnen eines Auto-Tell-Tabs aus der Datenbank geladen werden. 0 deaktiviert die Vorladung.</value>
<value>Wie viele frühere Flüsternachrichten beim Öffnen eines Auto-Flüster-Tabs aus der Datenbank geladen werden. 0 deaktiviert die Vorladung.</value>
</data>
<data name="Privacy_AutoTellTabs_Preload_Hint" xml:space="preserve">
<value>Greift nur, wenn Auto-Tell-Tabs im Chat-Tab aktiviert sind.</value>
<value>Greift nur, wenn Auto-Flüster-Tabs im Chat-Tab aktiviert sind.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe-Migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Settings umstrukturiert</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 hat die Settings in thematische Tabs umstrukturiert. Deine Chat-Datenbank und dein Nachrichtenverlauf bleiben unverändert. Settings wurden auf Defaults zurückgesetzt. Falls du das Privacy-Profil neu wählen willst, findest du den Reopen-Button im Datenschutz-Tab. Ein Backup der vorherigen Config liegt unter HellionChat.json.pre-v10-backup neben der aktiven Config-Datei.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-Tab-Struktur -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Allgemein</value>
</data>
@@ -590,9 +566,9 @@
<value>Über</value>
</data>
<!-- Hellion Chat — Sektions-Überschriften des Allgemein-Tabs -->
<!-- Hellion Chat — Sektions-Überschriften des Aussehen-Tabs -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Zeitstempel</value>
</data>
<!-- Hellion Chat — Sektions-Überschriften des Fenster-Tabs -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Fenster-Rahmen</value>
</data>
<!-- Hellion Chat — Sektions-Überschriften des Chat-Tabs -->
<!-- Hellion Chat — Chat-Tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Symbol-Picker-Button neben dem Chat-Eingang anzeigen</value>
</data>
@@ -621,23 +597,17 @@
<value>Fügt einen kleinen Button links neben dem Kanal-Indikator ein. Klick öffnet ein Popup mit FFXIV-Glyphen und einer kuratierten Symbol-Liste. Ausschalten für eine schlankere Eingabezeile.</value>
</data>
<!-- Hellion Chat — Sektions-Überschriften des Database-Tabs -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Speicherung</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Übersicht</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Wartung</value>
</data>
<!-- Hellion Chat — Sektions-Überschriften des Information-Tabs -->
<!-- Hellion Chat — Default-Tab-Presets (kanalspezifisch) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>System</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Wenn du mehrere Linkshells benutzt, empfiehlt der Maintainer einen Tab pro Shell für eine sauberere Übersicht. Tab duplizieren und je Kopie die Kanalauswahl einschränken.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Tab-Icon</value>
</data>
@@ -692,7 +662,7 @@
<value>Eingabe in Pop-Outs aktivieren</value>
</data>
<data name="Settings_Window_PopOutInputEnabled_Description" xml:space="preserve">
<value>Master-Switch: erlaubt direktes Tippen und Absenden in jedem Pop-Out-Fenster (inkl. Auto-Tell-Tabs). Channel-Wechsel im Pop-Out wirkt global wie im Hauptfenster; Text-Buffer und History-Cursor sind pro Pop-Out unabhängig.</value>
<value>Master-Switch: erlaubt direktes Tippen und Absenden in jedem Pop-Out-Fenster (inkl. Auto-Flüster-Tabs). Channel-Wechsel im Pop-Out wirkt global wie im Hauptfenster; Text-Buffer und History-Cursor sind pro Pop-Out unabhängig.</value>
</data>
<data name="Settings_Window_ResetPosition_Name" xml:space="preserve">
<value>Fenster-Position zurücksetzen</value>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Holt das Chat-Fenster und alle aktiven Pop-Outs zurück in die linke obere Ecke des Hauptmonitors. Hilfreich wenn ein Fenster nach einem Display-Layout-Wechsel außerhalb des sichtbaren Bereichs gelandet ist (Monitor abgezogen, Auflösung geändert). Das Plugin macht außerdem einmal pro Session einen automatischen Bounds-Check, dieser Button ist der manuelle Notausgang falls trotzdem etwas unerreichbar bleibt.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Neu in v0.6.0: Du kannst jetzt direkt im Pop-Out tippen. Master-Switch in den Fenster-Settings aktivieren.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Verstanden</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Fenster-Settings öffnen</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Du kannst jeden Chat-Tab als eigenes Fenster öffnen. Klicke auf das Fenster-Symbol oben rechts oder rechtsklicke den Tab. Neu in v0.6.1: die Pop-Out-Eingabe ist standardmäßig aktiv (abschaltbar unter Einstellungen → Fenster).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Verstanden</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Einstellungen öffnen</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat kann nicht starten, solange Chat 2 geladen ist.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Chat 2 in /xlplugins deaktivieren, danach Hellion Chat erneut aktivieren.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Allgemein</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Sprache, Eingabe, Audio und Performance.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Erscheinungsbild</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Fensterdeckkraft, Schriften, Bewegung</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Theme wählen oder eigenes importieren</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Fenster</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Wann das Fenster sichtbar ist und ob es sich bewegen lässt.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, Vorschau, Nachrichten-Verhalten und Emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Tabs</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Eigene Chat-Tabs anlegen und konfigurieren.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Datenbank</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Speicher, Migration, alte Bereinigung</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Über</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Erweiterungen, Version, Projektinformationen, Übersetzer und Changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Behalten</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Datenschutz zuerst</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Offen</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Daten &amp; Privatsphäre</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Privatsphäre-Filter, Aufbewahrung, Aufräumen, Export und Datenbank-Statistiken.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Erweitert (Shift+Klick zum Öffnen)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 hat das Settings-Menü neu sortiert und die alte „Stilüberschreiben"-Option entfernt (überholt durch das Theme-System aus 1.1.0). Deine restlichen Einstellungen bleiben unverändert. Die Fenster-Transparenz ist nach „Theme &amp; Layout" migriert. Ein Backup der vorherigen Config liegt unter pluginConfigs/HellionChat.json.pre-v16-backup neben der aktiven HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Plugin-Integrationen lassen HellionChat mit anderen installierten Dalamud-Plugins zusammenarbeiten. Jede Integration erkennt ihr Ziel automatisch und deaktiviert sich still, wenn das Ziel-Plugin fehlt.</value>
</data>
@@ -950,7 +848,7 @@
<value>Deaktiviert die Theme-Überblendung, die Hover-Animationen von Seitenleiste und Karten sowie das Pulsieren ungelesener Tabs. Theme-Wechsel und Hover-Zustände greifen dann sofort.</value>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Eingabe</value>
</data>
@@ -991,10 +889,7 @@
<value>Eingabe &amp; Vorschau</value>
</data>
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
<value>Auto-Flüster-Tabs</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Links &amp; Tooltips</value>
@@ -1063,10 +958,10 @@
<value>Änderungsprotokoll</value>
</data>
<data name="Settings_Chat_NotifyFailedTell_Name" xml:space="preserve">
<value>Benachrichtigung bei fehlgeschlagenem Tell</value>
<value>Benachrichtigung bei fehlgeschlagenem Flüstern</value>
</data>
<data name="Settings_Chat_NotifyFailedTell_Description" xml:space="preserve">
<value>Zeigt eine Toast-Meldung an, wenn ein von dir gesendeter Tell nicht zugestellt werden konnte (Empfänger offline, in einer Instanz oder hat dich blockiert).</value>
<value>Zeigt eine Toast-Meldung an, wenn ein von dir gesendeter Flüstern nicht zugestellt werden konnte (Empfänger offline, in einer Instanz oder hat dich blockiert).</value>
</data>
<data name="Settings_Chat_NotifyPluginDisclosure_Name" xml:space="preserve">
<value>Warnung vor dem Senden plugin-exklusiver Symbole</value>
@@ -1132,12 +1027,332 @@
<value>Hellion-Sound</value>
</data>
<data name="FailedTell_Notification_Generic" xml:space="preserve">
<value>Ein Tell konnte nicht zugestellt werden.</value>
<value>Ein Flüstern konnte nicht zugestellt werden.</value>
</data>
<data name="FailedTell_Notification_Named" xml:space="preserve">
<value>Tell an {0} konnte nicht zugestellt werden.</value>
<value>Flüstern an {0} konnte nicht zugestellt werden.</value>
</data>
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Diese Nachricht enthält plugin-exklusive Symbole, die andere Spieler als leere Kästchen sehen könnten. Drücke Enter erneut, um sie trotzdem zu senden.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Symbol einfügen</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Einstellungen</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Chat ausblenden (Enter holt ihn zurück)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Diesen Tab ins Hauptfenster zurückholen</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Es läuft gerade eine andere Datenbankoperation: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>Aufbewahrungslauf</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>Export</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>Bereinigung</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>Löschen des Verlaufs</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Der Datenschutzfilter ist aus, deshalb wird jeder Kanal gespeichert und nichts in der Datenbank widerspricht deinen Einstellungen. Schalte den Filter zuerst ein und wähle Kanäle aus.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Es ist kein Kanal ausgewählt, eine Bereinigung würde also den gesamten Verlauf löschen. Wähle die Kanäle aus, die du behalten willst, oder nimm den Löschen-Knopf, wenn wirklich alles weg soll.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Es sind {0:N0} Nachrichten gespeichert. Wenn du eine Kopie behalten willst, exportiere sie vor dem Löschen.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Strg+Umschalt: führt den Aufbewahrungslauf sofort aus, statt auf den täglichen Durchlauf zu warten. Löscht Nachrichten, die älter sind als die Grenzen oben.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Das Löschen des Verlaufs ist fehlgeschlagen. Es wurde nichts entfernt, siehe /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetrie</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Es wird keine Telemetrie erhoben. Das Plugin sendet nichts über dich oder deine Nutzung irgendwohin.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Auto-Übersetzung</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Zur neuesten Nachricht springen</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Kartenmarkierung einfügen &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Verlinkten Gegenstand einfügen &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>aus</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Verhalten</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Tastenkürzel</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Benachrichtigungen</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Anzeigemodi</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Verlauf</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Befehlshilfe</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Plugin-Hinweis</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Anordnung</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Deckkraft</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Größenverhalten</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Flüstern automatisch öffnen</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Seitenleiste</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Marke</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Links</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrationen</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Mitwirkende</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Lizenz</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Auf einen Knopf klicken, dann die Tastenkombination drücken. Esc löscht.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Zum nächsten Chat-Tab wechseln</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Zum vorherigen Chat-Tab wechseln</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Ein Wechsel baut den Schrift-Atlas neu auf, deshalb ist der Chat kurz leer.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24-Stunden-Uhr</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Verlauf früherer Sitzungen anzeigen</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Aus bedeutet, der Verlauf startet bei jedem Spielstart leer und füllt sich nur mit Nachrichten, die danach eintreffen.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Seite der Befehlshilfe</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Auf welcher Seite die Befehlsliste beim Tippen erscheint.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Modus für automatisches Flüster-Öffnen</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Wo ein Flüstern geöffnet wird, wenn er ankommt.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Bei jedem Flüstern zum Tab wechseln</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Sonst öffnet der Tab nach dem ersten im Hintergrund.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Seitenleiste</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Tabs oben</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Tab-Anordnung</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Wo die Tab-Liste im Hauptfenster sitzt.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Titelleiste anzeigen</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Titelleiste für Pop-Outs</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Verschieben erlauben</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Größe ändern erlauben</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Umschaltschwelle der Seitenleiste</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Unterhalb dieser Breite klappt die Seitenleiste zu Tabs oben, in Pixeln.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Position der Vorschau</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Vorschau nur beim Tippen zeigen</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea-Repository</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifest des eigenen Repos</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Aktives Theme: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Abzweigen und bearbeiten</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Eingebaute Themes lassen sich nicht direkt bearbeiten. Abzweigen legt eine eigene Kopie an, die du ändern und speichern kannst.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Theme bearbeiten</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>In Bearbeitung: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Flächen</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Rahmen</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Text</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identität</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Status</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Speichern</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Abbrechen</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Auf das Original zurücksetzen</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Zurücksetzen geht nicht, solange eine Abzweigung bearbeitet wird. Erst speichern oder abbrechen.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Erst deine Änderungen speichern oder verwerfen</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Eigene ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Aktives Theme abzweigen</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Theme-Datei importieren…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Pfad zur JSON-Datei (oder in den Ordner ziehen)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Theme exportieren</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Kühl</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Natürlich</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Klassisch</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (mitgeliefert)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Spielschrift</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Global: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Aktiv: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Nachricht schreiben...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplizieren</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>Vorschau</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>Wartung</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} Tab</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} Tabs</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} Flüstern</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} Flüstern</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} Nachr.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k Nachr.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Champion» Vorschau</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>offen</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Nicht eingeloggt</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Weitere Aktionen</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Δίχτυ ασφαλείας για ChatTypes που θα προστεθούν από μελλοντικά patches του FFXIV και δεν τα γνωρίζει ακόμη το plugin. Η προεπιλογή είναι ΑΠΕΝΕΡΓΟ (ελαχιστοποίηση δεδομένων). Ενεργοποίησε αν θέλεις να καταγράφονται πλήρως και τα μελλοντικά κανάλια.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Εφαρμογή φίλτρου στην υπάρχουσα βάση δεδομένων</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Το φίλτρο απορρήτου επηρεάζει μόνο νέα μηνύματα. Το παρακάτω cleanup σου επιτρέπει να αφαιρέσεις αναδρομικά ήδη αποθηκευμένα μηνύματα που δεν ταιριάζουν με την αποθηκευμένη whitelist σου.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Το cleanup χρησιμοποιεί την ΑΠΟΘΗΚΕΥΜΕΝΗ whitelist σου (Plugin.Config), όχι ανεπίσημες αλλαγές παραπάνω. Κάνε πρώτα Αποθήκευση αν θέλεις να εφαρμοστούν οι τρέχουσες αλλαγές σου.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Η χειροκίνητη εκτέλεση χρησιμοποιεί την ΑΠΟΘΗΚΕΥΜΕΝΗ πολιτική διατήρησης, όχι τις τιμές του slider παραπάνω. Κάνε πρώτα Αποθήκευση αν θέλεις να εφαρμοστούν οι τρέχουσες αλλαγές σου.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Η προεπισκόπηση είναι παλιά: η whitelist σου άλλαξε από την τελευταία ανανέωση. Κάνε κλικ στο Ανανέωση για επανυπολογισμό.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Εφαρμογή διατήρησης τώρα</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Εκτελεί αμέσως το cleanup διατήρησης με την ΑΠΟΘΗΚΕΥΜΕΝΗ πολιτική. Αποθήκευσε πρώτα τις αλλαγές σου.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Το cleanup διατήρησης εκτελείται στο παρασκήνιο…</value>
</data>
@@ -184,7 +172,7 @@
<value>Επίλεξε ένα αρχικό προφίλ. Μπορείς να ρυθμίσεις τα πάντα αργότερα στις Ρυθμίσεις → Απόρρητο.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Ελαχιστοποίηση δεδομένων (συνιστάται)</value>
<value>Ελαχιστοποίηση δεδομένων</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Αποθηκεύονται μόνο οι δικές σου συνομιλίες: tells, party, FC, linkshells, cross-world linkshells, alliance και ExtraChat. Το δημόσιο chat, οι διάλογοι NPC και το system spam απορρίπτονται σε επίπεδο αποθήκευσης. Η διατήρηση ακολουθεί τις προεπιλογές spec (tells 365 ημέρες, κανάλια ιδιωτικών συνομιλιών 90 ημέρες).</value>
@@ -226,7 +214,13 @@
<value>Καλωσόρισες στο Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Ένα fork του Chat 2 από το Hellion Forge με προεπιλογές φιλικές στο απόρρητο, συνεπή εμφάνιση brand και μερικές βελτιώσεις ευχρηστίας.</value>
<value>Το παράθυρο συνομιλίας σου από το Hellion Forge. Ιδιωτικότητα από την αρχή, σε 25 γλώσσες, και το στήνεις όπως θέλεις.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Το Hellion Chat ξεκίνησε ως fork του Chat 2. Έκτοτε τα δύο έχουν απομακρυνθεί τόσο ώστε οι κώδικές τους να μην είναι πλέον συμβατοί.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Τα plugin αποτελούν γκρίζα ζώνη στο Final Fantasy XIV: οι όροι χρήσης της Square Enix δεν τα καλύπτουν και ο Naoki Yoshida έχει ζητήσει δημόσια να μην διαφημίζονται. Κράτα λοιπόν το θέμα μακριά από τα Say, Yell, Shout και κάθε άλλο δημόσιο κανάλι.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Τρία σύντομα βήματα. Μπορείς να αλλάξεις τα πάντα αργότερα στις Ρυθμίσεις → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Τι αποθηκεύεται;</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = συνιστάται για τους περισσότερους παίκτες.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Συνιστάται</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Εμφάνιση</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Φόρτωση προηγούμενης συνεδρίας κατά την εκκίνηση</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Εφαρμογή φίλτρων σε μηνύματα από προηγούμενες συνεδρίες</value>
</data>
@@ -313,14 +304,11 @@
<value>(αμετάβλητο)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Δοκίμασέ το: πληκτρολόγησε /tell &lt;Όνομα Παίκτη&gt; στο chat. Το Hellion Chat ανοίγει αυτόματα μια αποκλειστική καρτέλα για τη συνομιλία και προφορτώνει τα τελευταία {0} μηνύματα.</value>
<value>Δοκίμασέ το: πληκτρολόγησε /tell &lt;Όνομα Παίκτη&gt; στο chat. Το Hellion Chat ανοίγει αυτόματα μια αποκλειστική καρτέλα για τη συνομιλία και προφορτώνει τα τελευταία {0} μηνύματα.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Ρυθμίσεις → Hellion Chat για προσαρμογή αργότερα</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Εξαγωγή (GDPR Art. 15 — Δικαίωμα πρόσβασης)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Εξαγωγή αποθηκευμένων μηνυμάτων ως Markdown, JSON ή CSV. Έτσι μπορείς να ανταποκριθείς σε αίτημα πρόσβασης από κάποιον του οποίου τα μηνύματα έχεις αποθηκεύσει, ή να πάρεις μαζί σου το δικό σου ιστορικό.</value>
</data>
@@ -457,7 +445,7 @@
<value>Μεταφραστές κοινότητας Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Ενεργά tells</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Ξεκαρφίτσωμα καρτέλας</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Προαγωγή σε μόνιμη</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Μετατρέπει αυτό το TempTell σε κανονική καρτέλα. Η σύνδεση tell με τον συνομιλητή καταργείται. Η καρτέλα θα συλλαμβάνει μηνύματα βάσει φίλτρων καναλιών από εδώ και εξής. Για "η καρτέλα επιβιώνει relog ενώ παραμένει συνδεδεμένη με αυτόν τον συνομιλητή", χρησιμοποίησε αντί αυτού το Καρφίτσωμα καρτέλας.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Οι καρφιτσωμένες καρτέλες επιβιώνουν relog και παραμένουν συνδεδεμένες με αυτόν τον συνομιλητή.</value>
</data>
@@ -504,7 +486,7 @@
<value>Καρφιτσωμένο: επιβιώνει relog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Σημείωση: Αν το XIV Messenger ή παρόμοιο plugin αποκλείει tells, απενεργοποίησε την επιλογή "Suppress DMs" εκεί ώστε το Hellion Chat να μπορεί να λαμβάνει tells και να ανοίγει τις αυτόματες καρτέλες.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Ιστορικό tell σε αυτόματες καρτέλες</value>
</data>
@@ -559,15 +541,9 @@
<value>Ισχύει μόνο όταν οι auto-tell tabs είναι ενεργοποιημένες στην καρτέλα Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Οι ρυθμίσεις αναδιαρθρώθηκαν</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Το Hellion Chat 0.5.0 αναδιάρθρωσε τις ρυθμίσεις σε θεματικές καρτέλες. Η βάση δεδομένων chat και το ιστορικό μηνυμάτων σου παραμένουν αναλλοίωτα. Οι ρυθμίσεις έχουν επαναφερθεί στις προεπιλογές. Αν θέλεις να επιλέξεις ξανά το προφίλ απορρήτου σου, το κουμπί Επαναφορά βρίσκεται στην καρτέλα Απόρρητο. Αντίγραφο ασφαλείας της προηγούμενης διαμόρφωσης βρίσκεται στο HellionChat.json.pre-v10-backup δίπλα στο ενεργό αρχείο διαμόρφωσης.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Γενικά</value>
</data>
@@ -590,9 +566,9 @@
<value>Πληροφορίες</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Χρονοσφραγίδες</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Πλαίσιο παραθύρου</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Εμφάνιση κουμπιού symbol-picker δίπλα στο πεδίο chat</value>
</data>
@@ -621,23 +597,17 @@
<value>Προσθέτει ένα μικρό κουμπί αριστερά της ένδειξης καναλιού που ανοίγει ένα popup με εικονίδια FFXIV και μια επιμελημένη λίστα συμβόλων. Απενεργοποίησε αν προτιμάς πιο λιτή γραμμή εισαγωγής.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Αποθήκευση</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Επισκόπηση</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Συντήρηση</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>System</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Αν χρησιμοποιείς πολλαπλά linkshells, ο maintainer συνιστά μία καρτέλα ανά shell για πιο καθαρή επισκόπηση. Αντίγραψε την καρτέλα και περιόρισε την επιλογή καναλιών σε κάθε αντίγραφο.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Εικονίδιο καρτέλας</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Μετακινεί το παράθυρο chat και όλα τα ενεργά pop-outs πίσω στην επάνω αριστερή γωνία της κύριας οθόνης. Χρήσιμο όταν ένα παράθυρο βρεθεί εκτός ορατής περιοχής μετά από αλλαγή διάταξης οθόνης (αποσύνδεση οθόνης, αλλαγή ανάλυσης). Το plugin εκτελεί επίσης αυτόματο έλεγχο ορίων μία φορά ανά συνεδρία. Αυτό το κουμπί είναι η χειροκίνητη διαφυγή αν κάτι παραμένει απρόσιτο.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Νέο στην v0.6.0: Μπορείς πλέον να πληκτρολογείς απευθείας σε pop-outs. Ενεργοποίησε τον κεντρικό διακόπτη στις ρυθμίσεις Παραθύρου.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Κατάλαβα</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Άνοιγμα ρυθμίσεων παραθύρου</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Μπορείς να ανοίξεις οποιαδήποτε καρτέλα chat ως δικό της παράθυρο. Κάνε κλικ στο εικονίδιο παραθύρου επάνω δεξιά ή δεξί κλικ στην καρτέλα. Νέο στην v0.6.1: η εισαγωγή σε pop-out είναι ενεργή εξ ορισμού (μπορεί να απενεργοποιηθεί στις Ρυθμίσεις → Παράθυρο).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Κατάλαβα</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Άνοιγμα ρυθμίσεων</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Το Hellion Chat δεν μπορεί να ξεκινήσει ενώ το Chat 2 είναι φορτωμένο.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Απενεργοποίησε το Chat 2 στο /xlplugins και μετά ενεργοποίησε ξανά το Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Γενικά</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Γλώσσα, εισαγωγή, ήχος και απόδοση.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Εμφάνιση</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Αδιαφάνεια παραθύρου, γραμματοσειρές, κίνηση</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Επίλεξε theme ή εισαγωγή δικού σου</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Παράθυρο</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Πότε το παράθυρο είναι ορατό και αν μπορεί να μετακινηθεί.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, προεπισκόπηση, συμπεριφορά μηνυμάτων και emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Καρτέλες</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Δημιουργία και ρύθμιση προσαρμοσμένων καρτελών chat.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Βάση δεδομένων</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Αποθήκευση, μετεγκατάσταση, παλαιό cleanup</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Σχετικά</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Επεκτάσεις, έκδοση, πληροφορίες έργου, μεταφραστές και changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Διατήρηση</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Απόρρητο πρώτα</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Ανοιχτό</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Δεδομένα και απόρρητο</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Φίλτρο απορρήτου, διατήρηση, cleanup, εξαγωγή και στατιστικά βάσης δεδομένων.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Για προχωρημένους (Shift+κλικ για άνοιγμα)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Το Hellion Chat 1.2.1 αναδιοργάνωσε το μενού ρυθμίσεων και αφαίρεσε την παλιά επιλογή "Override style" (αντικαταστάθηκε από το σύστημα themes από την έκδοση 1.1.0). Οι υπόλοιπες ρυθμίσεις σου παραμένουν αναλλοίωτες. Η διαφάνεια παραθύρου έχει μεταφερθεί στο "Theme &amp; Layout". Αντίγραφο ασφαλείας της προηγούμενης διαμόρφωσης βρίσκεται στο pluginConfigs/HellionChat.json.pre-v16-backup δίπλα στο ενεργό HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Οι ενσωματώσεις plugin επιτρέπουν στο HellionChat να συνεργάζεται με άλλα εγκατεστημένα Dalamud plugins. Κάθε ενσωμάτωση ανιχνεύει αυτόματα τον στόχο της και απενεργοποιείται σιωπηλά όταν το plugin-στόχος λείπει.</value>
</data>
@@ -955,7 +853,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Εισαγωγή</value>
</data>
@@ -998,9 +896,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Αυτόματες καρτέλες tell</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Εκφράσεις</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Σύνδεσμοι &amp; επεξηγήσεις</value>
</data>
@@ -1145,4 +1040,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Αυτό το μήνυμα περιέχει σύμβολα plugin που άλλοι παίκτες μπορεί να βλέπουν ως κενά κουτιά. Πιέστε Enter ξανά για αποστολή.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Εισαγωγή συμβόλου</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Ρυθμίσεις</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Απόκρυψη συνομιλίας (Enter για επαναφορά)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Επιστροφή αυτής της καρτέλας στο κύριο παράθυρο</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Εκτελείται ήδη μια άλλη λειτουργία βάσης δεδομένων: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>εκκαθάριση διατήρησης</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>εξαγωγή</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>εκκαθάριση</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>διαγραφή ιστορικού</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Το φίλτρο απορρήτου είναι απενεργοποιημένο, άρα αποθηκεύεται κάθε κανάλι και τίποτα στη βάση δεδομένων δεν έρχεται σε αντίθεση με τις ρυθμίσεις σας. Ενεργοποιήστε πρώτα το φίλτρο και επιλέξτε κανάλια.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Δεν έχει επιλεγεί κανένα κανάλι, οπότε μια εκκαθάριση θα διέγραφε όλο το ιστορικό. Επιλέξτε τα κανάλια που θέλετε να κρατήσετε ή χρησιμοποιήστε το κουμπί διαγραφής αν θέλετε πραγματικά να φύγουν όλα.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Έχουν αποθηκευτεί {0:N0} μηνύματα. Αν θέλετε να κρατήσετε αντίγραφο, εξαγάγετέ τα πριν τη διαγραφή.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: εκτελεί την εκκαθάριση διατήρησης αμέσως, χωρίς να περιμένει το ημερήσιο πέρασμα. Διαγράφει μηνύματα παλαιότερα από τα παραπάνω όρια.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Η διαγραφή του ιστορικού απέτυχε. Δεν αφαιρέθηκε τίποτα, δείτε /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Τηλεμετρία</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Δεν συλλέγεται τηλεμετρία. Το πρόσθετο δεν στέλνει πουθενά τίποτα για εσάς ή τη χρήση σας.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Αυτόματη μετάφραση</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Μετάβαση στο πιο πρόσφατο μήνυμα</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Εισαγωγή σημαίας χάρτη &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Εισαγωγή συνδεδεμένου αντικειμένου &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>ανενεργό</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Συμπεριφορά</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Συντομεύσεις</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Ειδοποιήσεις</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Λειτουργίες εμφάνισης</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Ιστορικό</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Βοήθεια εντολών</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Γνωστοποίηση πρόσθετου</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Λειτουργία διάταξης</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Αδιαφάνεια</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Συμπεριφορά μεγέθους</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Αυτόματο άνοιγμα tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Πλαϊνή μπάρα</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Επωνυμία</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Σύνδεσμοι</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Ενσωματώσεις</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Συντελεστές</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Άδεια</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Κάντε κλικ σε ένα κουμπί και μετά πατήστε τον συνδυασμό πλήκτρων. Το Esc καθαρίζει.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Μετάβαση στην επόμενη καρτέλα</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Μετάβαση στην προηγούμενη καρτέλα</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Η αλλαγή ξαναχτίζει τον άτλαντα γραμματοσειρών, οπότε η συνομιλία αδειάζει στιγμιαία.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24ωρο ρολόι</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Εμφάνιση ιστορικού από προηγούμενες συνεδρίες</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Απενεργοποιημένο σημαίνει ότι το αρχείο ξεκινά άδειο σε κάθε εκκίνηση και γεμίζει μόνο με μηνύματα που έρχονται μετά.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Πλευρά βοήθειας εντολών</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Σε ποια πλευρά εμφανίζεται η λίστα υποδείξεων ενώ πληκτρολογείτε.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Λειτουργία αυτόματου ανοίγματος tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Πού ανοίγει ένα tell όταν φτάνει.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Μετάβαση στην καρτέλα σε κάθε tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Διαφορετικά η καρτέλα ανοίγει στο παρασκήνιο μετά το πρώτο.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Πλαϊνή μπάρα</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Καρτέλες πάνω</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Τοποθέτηση καρτελών</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Πού βρίσκεται η λίστα καρτελών στο κύριο παράθυρο.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Εμφάνιση γραμμής τίτλου</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Εμφάνιση γραμμής τίτλου στα αποσπώμενα παράθυρα</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Να επιτρέπεται η μετακίνηση</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Αλλαγή μεγέθους επιτρέπεται</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Όριο αυτόματης εναλλαγής πλαϊνής μπάρας</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Κάτω από αυτό το πλάτος η πλαϊνή μπάρα διπλώνει σε καρτέλες πάνω, σε pixel.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Θέση προεπισκόπησης</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Προεπισκόπηση μόνο κατά την πληκτρολόγηση</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Αποθετήριο Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Δήλωση προσαρμοσμένου αποθετηρίου</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Ενεργό θέμα: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Διακλάδωση και επεξεργασία</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Τα ενσωματωμένα θέματα δεν επεξεργάζονται απευθείας. Η διακλάδωση δημιουργεί ένα προσαρμοσμένο αντίγραφο που μπορείτε να επεξεργαστείτε και να αποθηκεύσετε.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Επεξεργασία θέματος</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Επεξεργασία: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Επιφάνειες</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Περιγράμματα</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Κείμενο</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Ταυτότητα</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Κατάσταση</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Αποθήκευση</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Άκυρο</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Επαναφορά στην πηγή</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Η επαναφορά δεν είναι διαθέσιμη κατά την επεξεργασία διακλάδωσης. Αποθηκεύστε ή ακυρώστε πρώτα.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Αποθηκεύστε ή απορρίψτε πρώτα τις αλλαγές σας</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Προσαρμοσμένα ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Διακλάδωση ενεργού θέματος</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Εισαγωγή αρχείου θέματος…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Διαδρομή προς αρχείο JSON (ή σύρετε στον φάκελο)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Εξαγωγή θέματος</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Ψυχρά</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Φυσικά</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Κλασικά</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Ρετρό</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (ενσωματωμένη)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Γραμματοσειρά παιχνιδιού</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Καθολική: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Ενεργή: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Γράψτε ένα μήνυμα...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Αντιγραφή</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>προεπισκόπηση</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>συντήρηση</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} καρτέλα</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} καρτέλες</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} tell</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} tells</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} μην.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k μην.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Πρωταθλητής» Προεπισκόπηση</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>ανοιχτό</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Εκτός σύνδεσης</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Περισσότερες ενέργειες</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Red de seguridad para ChatTypes añadidos por futuros parches de FFXIV que el plugin aún no conoce. El valor predeterminado es DESACTIVADO (minimización de datos). Actívalo si quieres que los canales futuros también se registren completamente.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Aplicar filtro a la base de datos existente</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>El filtro de privacidad solo afecta a los mensajes nuevos. La limpieza de abajo te permite eliminar retroactivamente los mensajes ya almacenados que no coincidan con tu lista blanca guardada.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>La limpieza usa tu lista blanca GUARDADA (Plugin.Config), no los cambios sin guardar de arriba. Haz clic en Guardar primero si quieres que se apliquen tus cambios actuales.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>La ejecución manual usa tu política de retención GUARDADA, no los valores del deslizador de arriba. Haz clic en Guardar primero si quieres que la ejecución aplique tus cambios actuales.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>La vista previa está desactualizada: tu lista blanca ha cambiado desde la última actualización. Haz clic en Actualizar para recalcular.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Aplicar retención ahora</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Mayús: Ejecuta la limpieza de retención de inmediato usando la política GUARDADA. Guarda los cambios primero.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Limpieza de retención ejecutándose en segundo plano…</value>
</data>
@@ -184,7 +172,7 @@
<value>Elige un perfil inicial. Puedes ajustarlo todo más tarde en Ajustes → Privacidad.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Minimización de datos (recomendado)</value>
<value>Minimización de datos</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Solo se almacenan tus propias conversaciones: tells, escuadrón, FC, linkshells, linkshells cross-world, alianza y ExtraChat. El chat público, los diálogos de PNJ y el spam del sistema se descartan a nivel de almacenamiento. La retención sigue los valores predeterminados de spec (tells 365 días, canales de conversación propios 90 días).</value>
@@ -226,7 +214,13 @@
<value>Bienvenido a Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Un fork de Chat 2 de Hellion Forge con valores predeterminados respetuosos con la privacidad, diseño coherente con la marca y algunas mejoras de calidad de vida.</value>
<value>Tu ventana de chat, de Hellion Forge. Privacidad desde el primer momento, traducida a 25 idiomas, y la organizas a tu gusto.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat nació como un fork de Chat 2. Desde entonces ambos se han separado lo suficiente como para que sus bases de código ya no sean compatibles.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Los plugins son una zona gris en Final Fantasy XIV: las condiciones de uso de Square Enix no los contemplan, y Naoki Yoshida ha pedido públicamente que no se promocionen. Mantén el tema fuera de Decir, Gritar, Vociferar y de cualquier otro canal público.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Tres pasos breves. Puedes cambiar todo más tarde en Ajustes → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>¿Qué se almacena?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = recomendado para la mayoría de jugadores.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Recomendado</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Visual</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Cargar sesión anterior al iniciar</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Aplicar filtros a mensajes de sesiones anteriores</value>
</data>
@@ -313,14 +304,11 @@
<value>(sin cambios)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Pruébalo: escribe /tell &lt;Nombre del jugador&gt; en el chat. Hellion Chat abre una pestaña dedicada para la conversación y precarga los últimos {0} mensajes.</value>
<value>Pruébalo: escribe /tell &lt;Nombre del jugador&gt; en el chat. Hellion Chat abre una pestaña dedicada para la conversación y precarga los últimos {0} mensajes.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Ajustes → Hellion Chat para personalizar más tarde</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Exportar (GDPR Art. 15 — Derecho de acceso)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Exporta los mensajes almacenados como Markdown, JSON o CSV. Esto te permite atender una solicitud de acceso de una persona cuyos mensajes hayas almacenado, o llevarte tu propio historial.</value>
</data>
@@ -457,7 +445,7 @@
<value>Traductores de la comunidad de Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Tells activos</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Desfijar pestaña</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Convertir en pestaña permanente</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Convierte este TempTell en una pestaña regular. Se pierde el vínculo de tell con la persona: la pestaña captará mensajes según sus filtros de canal a partir de ahora. Para "la pestaña sobrevive al relog pero sigue vinculada a esta persona", usa Fijar pestaña en su lugar.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Las pestañas fijadas sobreviven al relog y permanecen vinculadas a esta persona de conversación.</value>
</data>
@@ -504,7 +486,7 @@
<value>Fijada: sobrevive al relog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Nota: Si XIV Messenger u otro plugin similar suprime los tells, desactiva la opción "Suppress DMs" allí para que Hellion Chat pueda recibir tells y abrir las pestañas automáticas.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Historial de tells en pestañas automáticas</value>
</data>
@@ -559,15 +541,9 @@
<value>Solo tiene efecto cuando las pestañas de tell automáticas están activadas en la pestaña Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Ajustes reestructurados</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 ha reestructurado los ajustes en pestañas temáticas. Tu base de datos de chat y tu historial de mensajes no han cambiado. Los ajustes se han restablecido a los valores predeterminados. Si quieres volver a seleccionar tu perfil de privacidad, el botón Reabrir está en la pestaña Privacidad. Una copia de seguridad de la configuración anterior se encuentra en HellionChat.json.pre-v10-backup junto al archivo de configuración activo.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>General</value>
</data>
@@ -590,9 +566,9 @@
<value>Acerca de</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Marcas de tiempo</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Marco de ventana</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Mostrar botón de selector de símbolos junto a la entrada del chat</value>
</data>
@@ -621,23 +597,17 @@
<value>Añade un pequeño botón a la izquierda del indicador de canal que abre un desplegable con iconos de FFXIV y una lista de símbolos curada. Desactívalo si prefieres una barra de entrada más sencilla.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Almacenamiento</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Resumen</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Mantenimiento</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Sistema</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Si usas varios linkshells, el mantenedor recomienda una pestaña por linkshell para una vista más clara. Duplica la pestaña y restringe la selección de canales en cada copia.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Icono de pestaña</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Mueve la ventana de chat y todas las ventanas emergentes activas de vuelta a la esquina superior izquierda del monitor principal. Útil cuando una ventana ha quedado fuera del área visible tras un cambio de configuración de pantalla (monitor desconectado, resolución cambiada). El plugin también realiza una comprobación automática de límites una vez por sesión; este botón es la salida de emergencia manual si algo sigue siendo inaccesible.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Novedad en v0.6.0: ahora puedes escribir directamente en las ventanas emergentes. Activa el interruptor maestro en los ajustes de Ventana.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Entendido</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Abrir ajustes de ventana</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Puedes abrir cualquier pestaña de chat como su propia ventana. Haz clic en el icono de ventana en la parte superior derecha o haz clic derecho en la pestaña. Novedad en v0.6.1: la entrada en ventanas emergentes está activa por defecto (se puede desactivar en Ajustes → Ventana).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Entendido</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Abrir ajustes</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat no puede iniciarse mientras Chat 2 está cargado.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Desactiva Chat 2 en /xlplugins y luego vuelve a activar Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>General</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Idioma, entrada, audio y rendimiento.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Apariencia</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Opacidad de ventana, fuentes, movimiento</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Elige un theme o importa el tuyo</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Ventana</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Cuándo es visible la ventana y si se puede mover.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, vista previa, comportamiento de mensajes y emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Pestañas</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Crea y configura pestañas de chat personalizadas.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Base de datos</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Almacenamiento, migración, limpieza de datos antiguos</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Acerca de</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Extensiones, versión, información del proyecto, traductores y changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Mantener</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Privacidad primero</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Abierto</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Datos y privacidad</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Filtro de privacidad, retención, limpieza, exportación y estadísticas de base de datos.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Avanzado (Mayús+clic para abrir)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 ha reorganizado el menú de ajustes y eliminado la antigua opción "Anular estilo" (reemplazada por el sistema de themes de la versión 1.1.0). El resto de tus ajustes no ha cambiado. La transparencia de ventana se ha migrado a "Theme &amp; Layout". Una copia de seguridad de la configuración anterior se encuentra en pluginConfigs/HellionChat.json.pre-v16-backup junto al HellionChat.json activo.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Las integraciones de plugins permiten que HellionChat trabaje junto con otros plugins de Dalamud instalados. Cada integración detecta automáticamente su objetivo y se desactiva silenciosamente cuando el plugin objetivo no está presente.</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Entrada</value>
</data>
@@ -999,9 +897,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Pestañas de tell automático</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Enlaces y sugerencias</value>
</data>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Este mensaje contiene símbolos exclusivos del plugin que otros jugadores pueden ver como cuadros vacíos. Presiona Intro de nuevo para enviarlo de todas formas.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Insertar símbolo</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Ajustes</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Ocultar el chat (Intro para recuperarlo)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Devolver esta pestaña a la ventana principal</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Ya se está ejecutando otra operación de base de datos: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>limpieza de retención</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>exportación</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>limpieza</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>borrado del historial</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>El filtro de privacidad está desactivado, así que se guarda cada canal y nada en la base de datos contradice tu configuración. Activa el filtro y elige canales primero.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>No hay ningún canal seleccionado, así que una limpieza borraría todo el historial. Elige los canales que quieras conservar, o usa el botón de borrar si de verdad quieres eliminarlo todo.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Hay {0:N0} mensajes guardados. Si quieres conservar una copia, expórtalos antes de borrar.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Mayús: ejecuta la limpieza de retención ahora mismo en lugar de esperar al barrido diario. Borra los mensajes más antiguos que los límites de arriba.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>No se pudo borrar el historial. No se eliminó nada, consulta /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetría</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>No se recopila telemetría. El plugin no envía nada sobre ti ni sobre tu uso a ninguna parte.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Traducción automática</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Ir al mensaje más reciente</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Insertar marca del mapa &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Insertar objeto enlazado &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>desactivado</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Comportamiento</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Atajos de teclado</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Notificaciones</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Modos de visualización</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Historial</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Ayuda de comandos</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Aviso del plugin</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Modo de disposición</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Opacidad</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Comportamiento de tamaño</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Apertura automática de tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Barra lateral</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Marca</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Enlaces</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integraciones</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Créditos</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licencia</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Haz clic en un botón y luego pulsa la combinación de teclas. Esc borra.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Cambiar a la pestaña siguiente</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Cambiar a la pestaña anterior</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Cambiarlo reconstruye el atlas de fuentes, así que el chat queda en blanco un momento.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>Reloj de 24 horas</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Mostrar el historial de sesiones anteriores</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Desactivado, el registro empieza vacío cada vez que se inicia el juego y solo se llena con los mensajes recibidos desde entonces.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Lado de la ayuda de comandos</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>En qué lado aparece la lista de sugerencias mientras escribes.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Modo de apertura automática de tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Dónde se abre un tell cuando llega.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Cambiar a la pestaña con cada tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Si no, la pestaña se abre en segundo plano tras el primero.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Barra lateral</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Pestañas superiores</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Ubicación de las pestañas</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Dónde se sitúa la lista de pestañas en la ventana principal.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Mostrar la barra de título</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Barra de título en pop-outs</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Permitir mover</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Permitir redimensionar</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Umbral de cambio automático de la barra lateral</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Por debajo de este ancho la barra lateral se pliega en pestañas superiores, en píxeles.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Posición de la vista previa</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Mostrar la vista previa solo al escribir</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Repositorio de Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifiesto del repositorio personalizado</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Tema activo: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Bifurcar y editar</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Los temas integrados no se pueden editar directamente. Bifurcar crea una copia personalizada que puedes editar y guardar.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Editar tema</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Editando: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Superficies</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Bordes</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Texto</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identidad</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Estado</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Guardar</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Cancelar</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Restablecer al original</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>No se puede restablecer mientras editas una bifurcación. Guarda o cancela primero.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Guarda o descarta tus cambios primero</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Personalizados ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Bifurcar el tema activo</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importar archivo de tema…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Ruta al archivo JSON (o arrástralo a la carpeta)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Exportar tema</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Fríos</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturales</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Clásicos</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (incluida)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Fuente del juego</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Global: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Activa: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Escribe un mensaje...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplicar</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>vista previa</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>mantenimiento</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} pestaña</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} pestañas</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} susurro</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} susurros</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} msj</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k msj</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Campeón» Vista previa</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>abierto</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Sesión no iniciada</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Más acciones</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Turvaverkko ChatType-tyypeille, jotka tulevat tulevissa FFXIV-päivityksissä eikä lisäosa vielä tunne niitä. Oletuksena POIS (tietojen minimointi). Ota käyttöön, jos haluat myös tulevat kanavat lokitettavan kokonaan.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Käytä suodatinta olemassa olevaan tietokantaan</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Tietosuojasuodatin vaikuttaa vain uusiin viesteihin. Alla oleva siivous antaa sinulle mahdollisuuden poistaa jälkikäteen jo tallennetut viestit, jotka eivät vastaa tallennettua sallittujen listaasi.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Siivous käyttää TALLENNETTUA sallittujen listaasi (Plugin.Config), ei yllä olevia tallentamattomia muutoksia. Napsauta Tallenna ensin, jos haluat muutostesi tulevan voimaan.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Manuaalinen ajo käyttää TALLENNETTUA säilytyskäytäntöäsi, ei yllä olevia liukusäätimen arvoja. Napsauta Tallenna ensin, jos haluat ajon soveltavan nykyiset muutoksesi.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Esikatselu on vanhentunut: sallittujen listasi on muuttunut viimeisen päivityksen jälkeen. Napsauta Päivitä laskeaksesi uudelleen.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Käytä säilytystä nyt</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Ajaa säilytykseen liittyvän siivouksen heti TALLENNETULLA käytännöllä. Tallenna muutoksesi ensin.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Säilytykseen liittyvä siivous käynnissä taustalla…</value>
</data>
@@ -184,7 +172,7 @@
<value>Valitse aloitusprofiili. Voit muuttaa kaikkea myöhemmin kohdassa Asetukset → Tietosuoja.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Tietojen minimointi (suositeltu)</value>
<value>Tietojen minimointi</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Vain omat keskustelusi tallennetaan: tellit, ryhmä, FC, linkshells, cross-world linkshells, allianssi ja ExtraChat. Julkinen chat, NPC-dialogit ja järjestelmäroskaviestit hylätään tallennusvaiheessa. Säilytys noudattaa spec-oletuksia (tellit 365 päivää, omat keskustelukanavat 90 päivää).</value>
@@ -226,7 +214,13 @@
<value>Tervetuloa Hellion Chatiin</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Chat 2 -haarautuma Hellion Forgelta, tietosuojatietoisilla oletuksilla, yhtenäisellä visuaalisella ilmeellä ja muutamilla käytännöllisillä parannuksilla.</value>
<value>Chat-ikkunasi Hellion Forgelta. Yksityisyys heti alusta, 25 kieltä, ja järjestät sen kuten haluat.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat sai alkunsa Chat 2:n forkkina. Sittemmin ne ovat eronneet toisistaan niin paljon, etteivät koodipohjat ole enää yhteensopivia.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Pluginit ovat Final Fantasy XIV:ssä harmaata aluetta: Square Enixin käyttöehdot eivät kata niitä, ja Naoki Yoshida on julkisesti pyytänyt, ettei niitä mainostettaisi. Pidä aihe siis poissa kanavilta Say, Yell, Shout ja kaikilta muilta julkisilta kanavilta.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Kolme lyhyttä vaihetta. Voit muuttaa kaikkea myöhemmin kohdassa Asetukset → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Mitä tallennetaan?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = suositeltu useimmille pelaajille.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Suositeltu</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Ulkoasu</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Lataa edellinen istunto käynnistyksen yhteydessä</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Käytä suodattimia aiempien istuntojen viesteihin</value>
</data>
@@ -313,14 +304,11 @@
<value>(ei muutosta)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Kokeile: kirjoita /tell &lt;Pelaajan nimi&gt; chattiin. Hellion Chat avaa erillisen välilehden keskustelulle ja esivalmistelee viimeiset {0} viestiä.</value>
<value>Kokeile: kirjoita /tell &lt;Pelaajan nimi&gt; chattiin. Hellion Chat avaa erillisen välilehden keskustelulle ja esivalmistelee viimeiset {0} viestiä.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Asetukset → Hellion Chat hienosäätöä varten myöhemmin</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Vie (GDPR Art. 15 — Tarkastusoikeus)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Vie tallennetut viestit Markdown-, JSON- tai CSV-muodossa. Näin voit täyttää tietopyynnön henkilöltä, jonka viestejä olet tallentanut, tai ottaa oman historiasi mukaasi.</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2:n yhteisökääntäjät (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Aktiiviset tellit</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Irrota välilehti</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Muuta pysyväksi välilehdeksi</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Muuttaa tämän TempTell-välilehden tavalliseksi välilehdeksi. Tell-sidonta kumppaniin poistetaan: välilehti poimii viestit kanavasuodattimiensa perusteella tästä eteenpäin. Jos haluat "välilehti selviää relogista sidottuna tähän kumppaniin", käytä sen sijaan Kiinnitä välilehti -toimintoa.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Kiinnitetyt välilehdet selviävät relogista ja pysyvät sidottuina tähän keskustelukumppaniin.</value>
</data>
@@ -504,7 +486,7 @@
<value>Kiinnitetty: selviää relogista.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Huomio: Jos XIV Messenger tai vastaava lisäosa estää tellit, poista siellä käytöstä "Suppress DMs" -asetus, jotta Hellion Chat voi vastaanottaa tellejä ja avata auto-välilehdet.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Tell-historia auto-välilehdissä</value>
</data>
@@ -559,15 +541,9 @@
<value>Tulee voimaan vain, kun auto-tell-välilehdet ovat käytössä Chat-välilehdellä.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Asetukset uudelleenjärjestetty</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 on uudelleenjärjestänyt asetukset temaattisiin välilehtiin. Chat-tietokantasi ja viestihistoriasi pysyvät muuttumattomina. Asetukset on nollattu oletuksiin. Jos haluat valita tietosuojaprofiilin uudelleen, Avaa uudelleen -painike on Tietosuoja-välilehdellä. Varmuuskopio aiemmasta asetustiedostosta löytyy nimellä HellionChat.json.pre-v10-backup aktiivisen asetustiedoston vierestä.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Yleiset</value>
</data>
@@ -590,9 +566,9 @@
<value>Tietoja</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Teema</value>
</data>
@@ -606,14 +582,14 @@
<value>Aikaleimat</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Ikkunakehys</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Näytä symbolinvalitsinpainike chat-syötteen vieressä</value>
</data>
@@ -621,23 +597,17 @@
<value>Lisää pienen painikkeen kanavan ilmaisimen vasemmalle puolelle, joka avaa ponnahdusikkunan FFXIV-kuvakkeilla ja kuratoitulla symbolilistalla. Poista käytöstä, jos haluat siistimmän syöterivin.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Tallennus</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Yleiskatsaus</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Ylläpito</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Järjestelmä</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emootiot</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Jos käytät useita linkshell-ryhmiä, ylläpitäjä suosittelee yhtä välilehteä kullekin, jotta yleiskatsaus pysyy selkeänä. Kopioi välilehti ja rajaa kanavan valinta kussakin kopiossa.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Välilehden kuvake</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Siirtää chat-ikkunan ja kaikki aktiiviset irrotetut ikkunat takaisin ensisijaisen näytön vasempaan yläkulmaan. Hyödyllinen, kun ikkuna on päätynyt näkyvän alueen ulkopuolelle näyttöasettelumuutoksen jälkeen (näyttö irrotettu, tarkkuus muutettu). Lisäosa suorittaa myös automaattisen rajatarkistuksen kerran istunnon aikana; tämä painike on manuaalinen pelastusreitti, jos jokin silti päätyy ulottumattomiin.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Uutta versiossa v0.6.0: voit nyt kirjoittaa suoraan irrotettuissa ikkunoissa. Ota pääkytkin käyttöön Ikkuna-asetuksissa.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Selvä</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Avaa ikkunan asetukset</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Voit avata minkä tahansa chat-välilehden omana ikkunanaan. Napsauta ikkunakuvaketta oikeassa yläkulmassa tai hiiren oikealla painikkeella välilehteä. Uutta versiossa v0.6.1: irrotetun ikkunan syöte on oletuksena aktiivinen (voidaan poistaa käytöstä kohdassa Asetukset → Ikkuna).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Selvä</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Avaa asetukset</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat ei voi käynnistyä, kun Chat 2 on ladattuna.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Poista Chat 2 käytöstä /xlplugins-kohdassa, ota sitten Hellion Chat uudelleen käyttöön.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Yleiset</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Kieli, syöte, ääni ja suorituskyky.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Ulkoasu</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Ikkunan läpinäkyvyys, fontit, liike</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Teemat</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Valitse teema tai tuo oma</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Ikkuna</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Milloin ikkuna on näkyvissä ja voiko sitä siirtää.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tellit, esikatselu, viestien toiminta ja emotet.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Välilehdet</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Luo ja määritä mukautettuja chat-välilehtiä.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Tietokanta</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Tallennus, siirto, vanhan datan siivous</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Tietoja</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Laajennukset, versio, projektin tiedot, kääntäjät ja changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Teemat</value>
</data>
@@ -803,7 +707,7 @@
<value>Säilytä</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Yksityisyys ensin</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Avoin</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Tiedot ja yksityisyys</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Yksityisyyssuodatin, säilytys, siivous, vienti ja tietokantatilastot.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Teema</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Lisäasetukset (Shift+napsauta avataksesi)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 on uudelleenjärjestänyt asetusvalikon ja poistanut vanhan "Ohita tyyli" -vaihtoehdon (korvattu versiossa 1.1.0 esitellyllä teemajärjestelmällä). Muut asetuksesi pysyvät muuttumattomina. Ikkunan läpinäkyvyys on siirretty kohtaan "Teema &amp; asettelu". Varmuuskopio aiemmasta asetustiedostosta löytyy nimellä pluginConfigs/HellionChat.json.pre-v16-backup aktiivisen HellionChat.json-tiedoston vierestä.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Lisäosaintegraatiot mahdollistavat HellionChatin yhteistyön muiden asennettujen Dalamud-lisäosien kanssa. Jokainen integraatio tunnistaa kohteensa automaattisesti ja poistaa itsensä hiljaisesti käytöstä, kun kohdalisäosa puuttuu.</value>
</data>
@@ -955,7 +853,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Syöte</value>
</data>
@@ -998,9 +896,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Automaattiset tell-välilehdet</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotet</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Linkit ja työkaluvihjeet</value>
</data>
@@ -1145,4 +1040,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Tämä viesti sisältää plugin-symboleja, jotka muut pelaajat saattavat nähdä tyhjinä ruutuina. Paina Enter uudelleen lähettääksesi joka tapauksessa.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Lisää symboli</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Asetukset</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Piilota chat (Enter palauttaa sen)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Palauta tämä välilehti pääikkunaan</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Toinen tietokantatoiminto on käynnissä: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>säilytysajo</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>vienti</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>siivous</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>historian tyhjennys</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Yksityisyyssuodatin on pois päältä, joten jokainen kanava tallennetaan eikä mikään tietokannassa ole ristiriidassa asetustesi kanssa. Kytke suodatin päälle ja valitse kanavat ensin.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Yhtään kanavaa ei ole valittu, joten siivous poistaisi koko historian. Valitse säilytettävät kanavat tai käytä tyhjennyspainiketta, jos haluat todella poistaa kaiken.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Tallennettuna on {0:N0} viestiä. Jos haluat säilyttää kopion, vie ne ennen tyhjennystä.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: suorittaa säilytysajon heti sen sijaan, että odottaisi päivittäistä ajoa. Poistaa yllä olevia rajoja vanhemmat viestit.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Historian tyhjennys epäonnistui. Mitään ei poistettu, katso /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetria</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Telemetriaa ei kerätä. Lisäosa ei lähetä mitään sinusta tai käytöstäsi minnekään.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Automaattikäännös</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Siirry uusimpaan viestiin</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Lisää karttamerkki &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Lisää linkitetty esine &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>pois</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Toiminta</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Pikanäppäimet</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Ilmoitukset</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Näyttötilat</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Historia</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Komento-ohje</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Lisäosailmoitus</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Asettelutila</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Läpinäkymättömyys</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Koon muuttaminen</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Tellin automaattinen avaus</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Sivupalkki</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Tuotemerkki</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Linkit</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integraatiot</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Tekijät</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Lisenssi</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Napsauta painiketta ja paina sitten näppäinyhdistelmää. Esc tyhjentää.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Siirry seuraavaan välilehteen</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Siirry edelliseen välilehteen</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Vaihto rakentaa fonttiatlaksen uudelleen, joten chat on hetken tyhjä.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24 tunnin kello</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Näytä aiempien istuntojen historia</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Pois päältä loki alkaa tyhjänä joka käynnistyksellä ja täyttyy vain sen jälkeen saapuneilla viesteillä.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Komento-ohjeen puoli</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Kummalla puolella komentovihjeluettelo näkyy kirjoitettaessa.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Tellin automaattisen avauksen tila</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Missä tell avautuu saapuessaan.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Vaihda välilehteen jokaisella tellillä</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Muuten välilehti avautuu taustalle ensimmäisen jälkeen.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Sivupalkki</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Ylävälilehdet</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Välilehtien sijainti</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Missä välilehtiluettelo sijaitsee pääikkunassa.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Näytä otsikkopalkki</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Näytä otsikkopalkki irrotetuissa ikkunoissa</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Salli siirtäminen</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Salli koon muuttaminen</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Sivupalkin automaattisen vaihdon raja</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Tämän leveyden alapuolella sivupalkki taittuu ylävälilehdiksi, pikseleinä.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Esikatselun sijainti</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Näytä esikatselu vain kirjoitettaessa</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea-tietovarasto</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Mukautetun tietovaraston manifesti</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Aktiivinen teema: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Haaroita ja muokkaa</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Sisäänrakennettuja teemoja ei voi muokata suoraan. Haaroitus luo mukautetun kopion, jota voit muokata ja tallentaa.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Muokkaa teemaa</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Muokataan: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Pinnat</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Reunat</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Teksti</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identiteetti</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Tila</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Tallenna</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Peruuta</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Palauta lähteeseen</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Palautus ei ole käytettävissä haaraa muokattaessa. Tallenna tai peruuta ensin.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Tallenna tai hylkää muutoksesi ensin</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Mukautetut ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Haaroita aktiivinen teema</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Tuo teematiedosto…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSON-tiedoston polku (tai vedä kansioon)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Vie teema</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Viileät</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Luonnolliset</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Klassiset</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (mukana)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Pelin fontti</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Yleinen: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Aktiivinen: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Kirjoita viesti...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Kahdenna</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>esikatselu</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>ylläpito</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} välilehti</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} välilehteä</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} kuiskaus</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} kuiskausta</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} vie.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k vie.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Mestari» Esikatselu</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>auki</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Ei kirjautuneena</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Lisää toimintoja</value>
</data>
</root>
+376 -161
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Filet de sécurité pour les ChatTypes ajoutés par de futurs correctifs de FFXIV que le plugin ne connaît pas encore. Désactivé par défaut (minimisation des données). Activez cette option si vous souhaitez que les futurs canaux soient également enregistrés intégralement.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Appliquer le filtre à la base de données existante</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Le filtre de confidentialité n'affecte que les nouveaux messages. Le nettoyage ci-dessous vous permet de supprimer rétroactivement les messages déjà enregistrés qui ne correspondent pas à votre liste blanche enregistrée.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Le nettoyage utilise votre liste blanche ENREGISTRÉE (Plugin.Config), pas les modifications non enregistrées ci-dessus. Cliquez d'abord sur Enregistrer si vous souhaitez que vos modifications actuelles soient appliquées.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>L'exécution manuelle utilise votre politique de conservation ENREGISTRÉE, pas les valeurs du curseur ci-dessus. Cliquez d'abord sur Enregistrer si vous souhaitez que l'exécution applique vos modifications actuelles.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>L'aperçu est obsolète : votre liste blanche a été modifiée depuis le dernier rafraîchissement. Cliquez sur Rafraîchir pour recalculer.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Appliquer la conservation maintenant</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Maj : exécute immédiatement le nettoyage de conservation en utilisant la politique ENREGISTRÉE. Enregistrez d'abord vos modifications.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Nettoyage de conservation en cours en arrière-plan…</value>
</data>
@@ -184,10 +172,10 @@
<value>Choisissez un profil de départ. Vous pouvez tout ajuster par la suite dans Paramètres → Confidentialité.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Minimisation des données (recommandé)</value>
<value>Minimisation des données</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Seules vos propres conversations sont enregistrées : tells, équipe, CL, linkshells, linkshells inter-mondes, alliance et ExtraChat. Le chat public, les dialogues PNJ et le spam système sont écartés au niveau du stockage. La conservation suit les valeurs par défaut de la spécification (tells 365 jours, vos canaux de conversation 90 jours).</value>
<value>Seules vos propres conversations sont enregistrées : messages privés, équipe, CL, linkshells, linkshells inter-mondes, alliance et ExtraChat. Le chat public, les dialogues PNJ et le spam système sont écartés au niveau du stockage. La conservation suit les valeurs par défaut de la spécification (messages privés 365 jours, vos canaux de conversation 90 jours).</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Apply" xml:space="preserve">
<value>Appliquer la minimisation des données</value>
@@ -226,7 +214,13 @@
<value>Bienvenue dans Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Un fork de Chat 2 par Hellion Forge avec des valeurs par défaut axées sur la confidentialité, une identité visuelle cohérente et quelques améliorations de confort.</value>
<value>Ta fenêtre de discussion, signée Hellion Forge. Confidentialité par défaut, traduite en 25 langues, et à agencer comme tu veux.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat est né d'un fork de Chat 2. Les deux se sont depuis suffisamment éloignés pour que les bases de code ne soient plus compatibles.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Les plugins sont une zone grise dans Final Fantasy XIV : les conditions d'utilisation de Square Enix ne les couvrent pas, et Naoki Yoshida a publiquement demandé de ne pas en faire la promotion. Évite donc le sujet dans Dire, Crier, Hurler et tout autre canal public.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Trois étapes courtes. Vous pouvez tout modifier plus tard dans Paramètres → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Qu'est-ce qui est enregistré ?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = recommandé pour la plupart des joueurs.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Recommandé</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -268,19 +262,16 @@
<value>Historique</value>
</data>
<data name="Wizard_Step3_Section_TellTabs" xml:space="preserve">
<value>Onglets de tell</value>
<value>Onglets de message privé</value>
</data>
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Visuel</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Charger la session précédente au démarrage</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Appliquer les filtres aux messages des sessions précédentes</value>
</data>
<data name="Wizard_Step3_AutoTellTabsHistoryPreload_Label" xml:space="preserve">
<value>Précharger N messages de tell à l'ouverture d'un onglet automatique</value>
<value>Précharger N messages privés à l'ouverture d'un onglet automatique</value>
</data>
<data name="Wizard_Step3_UseCompactDensity_Label" xml:space="preserve">
<value>Densité compacte</value>
@@ -304,7 +295,7 @@
<value>Historique : {0}</value>
</data>
<data name="Wizard_Step4_Summary_TellTabs" xml:space="preserve">
<value>Onglets de tell : préchargement de {0} messages</value>
<value>Onglets de message privé : préchargement de {0} messages</value>
</data>
<data name="Wizard_Step4_Summary_Visual" xml:space="preserve">
<value>Visuel : {0}</value>
@@ -313,14 +304,11 @@
<value>(inchangé)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Essayez : tapez /tell &lt;Nom du joueur&gt; dans le chat. Hellion Chat ouvre un onglet dédié à la conversation et précharge les {0} derniers messages.</value>
<value>Essayez : tapez /tell &lt;Nom du joueur&gt; dans le chat. Hellion Chat ouvre un onglet dédié à la conversation et précharge les {0} derniers messages.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Paramètres → Hellion Chat pour affiner plus tard</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Exportation (RGPD art. 15 — Droit d'accès)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Exportez les messages enregistrés en Markdown, JSON ou CSV. Cela vous permet de répondre à une demande d'accès émanant d'une personne dont vous avez enregistré les messages, ou d'emporter votre propre historique.</value>
</data>
@@ -457,9 +445,9 @@
<value>Traducteurs communautaires de Chat 2 (en amont)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Tells actifs</value>
<value>Messages privés actifs</value>
</data>
<data name="AutoTellTabs_HistorySeparator" xml:space="preserve">
<value>— Conversations précédentes —</value>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Désépingler l'onglet</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Promouvoir en permanent</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Transforme ce TempTell en onglet régulier. Le lien du tell avec le partenaire est rompu. L'onglet capturera désormais les messages selon ses filtres de canaux. Pour « onglet qui survit à la reconnexion en restant lié à ce partenaire », utilisez Épingler l'onglet à la place.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Les onglets épinglés survivent à la reconnexion et restent liés à ce partenaire de conversation.</value>
</data>
@@ -495,18 +477,18 @@
<value>Largeur de la barre latérale</value>
</data>
<data name="Settings_ThemeAndLayout_SidebarWidth_Description" xml:space="preserve">
<value>Largeur de la barre latérale d'onglets en pixels. La valeur par défaut (44 px) n'affiche que les icônes ; élargissez-la pour permettre l'affichage complet d'en-têtes de section comme « Tells actifs (3) » sans troncature.</value>
<value>Largeur de la barre latérale d'onglets en pixels. La valeur par défaut (44 px) n'affiche que les icônes ; élargissez-la pour permettre l'affichage complet d'en-têtes de section comme « Messages privés actifs (3) » sans troncature.</value>
</data>
<data name="PinTab_LimitReached" xml:space="preserve">
<value>Maximum de {0} onglets de tell épinglés atteint. Désépinglez-en un d'abord, ou utilisez Promouvoir en permanent.</value>
<value>Maximum de {0} onglets de message privé épinglés atteint. Désépinglez-en un d'abord, ou utilisez Promouvoir en permanent.</value>
</data>
<data name="PinTab_PinnedTooltip" xml:space="preserve">
<value>Épinglé : survit à la reconnexion.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Onglets de tell automatiques</value>
<value>Onglets de message privé automatiques</value>
</data>
<data name="ChatLog_AutoTellTabs_Enable_Name" xml:space="preserve">
<value>Ouvrir automatiquement un onglet par partenaire de conversation pour chaque /tell</value>
@@ -515,22 +497,22 @@
<value>Dès que vous recevez ou envoyez un /tell, un onglet temporaire est automatiquement ouvert pour ce joueur. Les onglets sont supprimés à la déconnexion.</value>
</data>
<data name="ChatLog_AutoTellTabs_Limit_Name" xml:space="preserve">
<value>Nombre maximum d'onglets de tell automatiques</value>
<value>Nombre maximum d'onglets de message privé automatiques</value>
</data>
<data name="ChatLog_AutoTellTabs_Limit_Description" xml:space="preserve">
<value>Lorsque la limite est atteinte, les onglets salués avec l'activité la plus ancienne sont fermés en premier. Les changements prennent effet au prochain /tell. Cette limite s'applique au pool géré automatiquement. Les onglets de tell épinglés (clic droit → Épingler l'onglet) vivent dans un pool distinct pouvant contenir jusqu'à 5 éléments et survivent à la reconnexion.</value>
<value>Lorsque la limite est atteinte, les onglets salués avec l'activité la plus ancienne sont fermés en premier. Les changements prennent effet au prochain /tell. Cette limite s'applique au pool géré automatiquement. Les onglets de message privé épinglés (clic droit → Épingler l'onglet) vivent dans un pool distinct pouvant contenir jusqu'à 5 éléments et survivent à la reconnexion.</value>
</data>
<data name="ChatLog_AutoTellTabs_Compact_Name" xml:space="preserve">
<value>Affichage compact</value>
</data>
<data name="ChatLog_AutoTellTabs_Compact_Description" xml:space="preserve">
<value>Affiche uniquement un fin séparateur entre les onglets réguliers et les onglets de tell automatiques, sans en-tête de section.</value>
<value>Affiche uniquement un fin séparateur entre les onglets réguliers et les onglets de message privé automatiques, sans en-tête de section.</value>
</data>
<data name="ChatLog_AutoTellTabs_GreetedToggle_Name" xml:space="preserve">
<value>Afficher le bouton « Marquer comme salué »</value>
</data>
<data name="ChatLog_AutoTellTabs_GreetedToggle_Description" xml:space="preserve">
<value>Ajoute un bouton à côté de chaque onglet de tell automatique pour marquer un partenaire de conversation comme déjà salué. Le nom de l'onglet est alors atténué. Utile pour les hôtes de club qui gèrent de nombreuses conversations en parallèle. Désactivé par défaut.</value>
<value>Ajoute un bouton à côté de chaque onglet de message privé automatique pour marquer un partenaire de conversation comme déjà salué. Le nom de l'onglet est alors atténué. Utile pour les hôtes de club qui gèrent de nombreuses conversations en parallèle. Désactivé par défaut.</value>
</data>
<data name="ChatLog_AutoTellTabs_OpenAsPopout_Name" xml:space="preserve">
<value>Ouvrir les nouveaux onglets /tell directement comme fenêtres détachées</value>
@@ -539,35 +521,29 @@
<value>Quand cette option est active, chaque onglet /tell nouvellement créé est immédiatement ouvert dans sa propre fenêtre. Fermer la fenêtre renvoie l'onglet dans la barre latérale.</value>
</data>
<data name="ChatLog_AutoTellTabs_PreloadHint" xml:space="preserve">
<value>Le nombre de tells préchargés peut être configuré dans l'onglet Confidentialité.</value>
<value>Le nombre de messages privés préchargés peut être configuré dans l'onglet Confidentialité.</value>
</data>
<data name="ChatLog_AutoTellTabs_ConflictHint" xml:space="preserve">
<value>Remarque : si XIV Messenger ou un plugin similaire supprime les tells, désactivez l'option « Suppress DMs » à cet endroit afin que Hellion Chat puisse recevoir les tells et ouvrir les onglets automatiques.</value>
<value>Remarque : si XIV Messenger ou un plugin similaire supprime les messages privés, désactivez l'option « Suppress DMs » à cet endroit afin que Hellion Chat puisse recevoir les messages privés et ouvrir les onglets automatiques.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Historique des tells dans les onglets automatiques</value>
<value>Historique des messages privés dans les onglets automatiques</value>
</data>
<data name="Privacy_AutoTellTabs_Preload_Name" xml:space="preserve">
<value>Nombre de tells préchargés</value>
<value>Nombre de messages privés préchargés</value>
</data>
<data name="Privacy_AutoTellTabs_Preload_Description" xml:space="preserve">
<value>Combien de messages de tell antérieurs sont chargés depuis la base de données à l'ouverture d'un onglet de tell automatique. 0 désactive le préchargement.</value>
<value>Combien de messages privés antérieurs sont chargés depuis la base de données à l'ouverture d'un onglet de message privé automatique. 0 désactive le préchargement.</value>
</data>
<data name="Privacy_AutoTellTabs_Preload_Hint" xml:space="preserve">
<value>N'a d'effet que lorsque les onglets de tell automatiques sont activés dans l'onglet Chat.</value>
<value>N'a d'effet que lorsque les onglets de message privé automatiques sont activés dans l'onglet Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Paramètres restructurés</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 a restructuré les paramètres en onglets thématiques. Votre base de données de chat et votre historique de messages restent inchangés. Les paramètres ont été réinitialisés à leurs valeurs par défaut. Si vous souhaitez resélectionner votre profil de confidentialité, le bouton Rouvrir se trouve dans l'onglet Confidentialité. Une sauvegarde de la configuration précédente est disponible dans HellionChat.json.pre-v10-backup, à côté du fichier de configuration actif.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Général</value>
</data>
@@ -590,9 +566,9 @@
<value>À propos</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Thème</value>
</data>
@@ -606,14 +582,14 @@
<value>Horodatages</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Cadre de la fenêtre</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Afficher le bouton de sélection de symboles à côté de la saisie</value>
</data>
@@ -621,23 +597,17 @@
<value>Ajoute un petit bouton à gauche de l'indicateur de canal qui ouvre une fenêtre contextuelle contenant des icônes FFXIV et une liste de symboles soigneusement sélectionnés. Désactivez si vous préférez une barre de saisie plus épurée.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Stockage</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Visualiseur</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Maintenance</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Système</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Compagnie libre</value>
</data>
@@ -654,7 +624,7 @@
<value>Si vous utilisez plusieurs linkshells, le mainteneur recommande un onglet par linkshell pour une meilleure vue d'ensemble. Dupliquez l'onglet et restreignez la sélection de canaux dans chaque copie.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Icône d'onglet</value>
</data>
@@ -692,7 +662,7 @@
<value>Activer la saisie dans les fenêtres détachées</value>
</data>
<data name="Settings_Window_PopOutInputEnabled_Description" xml:space="preserve">
<value>Interrupteur principal : permet de taper et d'envoyer directement dans n'importe quelle fenêtre détachée (y compris les onglets de tell automatiques). Le changement de canal dans une fenêtre détachée agit globalement comme dans la fenêtre principale ; le tampon de texte et le curseur d'historique sont indépendants pour chaque fenêtre détachée.</value>
<value>Interrupteur principal : permet de taper et d'envoyer directement dans n'importe quelle fenêtre détachée (y compris les onglets de message privé automatiques). Le changement de canal dans une fenêtre détachée agit globalement comme dans la fenêtre principale ; le tampon de texte et le curseur d'historique sont indépendants pour chaque fenêtre détachée.</value>
</data>
<data name="Settings_Window_ResetPosition_Name" xml:space="preserve">
<value>Réinitialiser la position de la fenêtre</value>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Ramène la fenêtre de chat et toutes les fenêtres détachées actives dans le coin supérieur gauche de l'écran principal. Utile lorsqu'une fenêtre s'est retrouvée hors de la zone visible après un changement de configuration d'affichage (déconnexion d'un moniteur, changement de résolution). Le plugin effectue également une vérification automatique des limites une fois par session ; ce bouton est l'issue de secours manuelle si quelque chose reste malgré tout inaccessible.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Nouveauté de la v0.6.0 : vous pouvez désormais saisir directement dans les fenêtres détachées. Activez l'interrupteur principal dans les paramètres de la fenêtre.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Compris</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Ouvrir les paramètres de la fenêtre</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Vous pouvez ouvrir n'importe quel onglet de chat comme sa propre fenêtre. Cliquez sur l'icône de fenêtre en haut à droite ou faites un clic droit sur l'onglet. Nouveauté de la v0.6.1 : la saisie dans les fenêtres détachées est active par défaut (peut être désactivée dans Paramètres → Fenêtre).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Compris</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Ouvrir les paramètres</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat ne peut pas démarrer tant que Chat 2 est chargé.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Désactivez Chat 2 dans /xlplugins, puis réactivez Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Général</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Langue, saisie, audio et performance.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Apparence</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Opacité de la fenêtre, polices, animations</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Thèmes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Choisissez un thème ou importez le vôtre</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Fenêtre</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Quand la fenêtre est visible et si elle peut être déplacée.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, aperçu, comportement des messages et emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Onglets</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Créez et configurez des onglets de chat personnalisés.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Base de données</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Stockage, migration, nettoyage des données historiques</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>À propos</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Extensions, version, informations du projet, traducteurs et journal des modifications.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Thèmes</value>
</data>
@@ -803,7 +707,7 @@
<value>Conserver</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Confidentialité</value>
<value>Confidentialité d'abord</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Ouvert</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Données et confidentialité</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Filtre de confidentialité, conservation, nettoyage, exportation et statistiques de la base de données.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Thème</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Avancé (Maj+clic pour ouvrir)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 a réorganisé le menu des paramètres et supprimé l'ancienne option « Remplacer le style » (remplacée par le système de thèmes de la 1.1.0). Vos autres paramètres restent inchangés. La transparence de la fenêtre a été migrée vers « Thème et mise en page ». Une sauvegarde de la configuration précédente est disponible dans pluginConfigs/HellionChat.json.pre-v16-backup, à côté du HellionChat.json actif.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Les intégrations de plugins permettent à HellionChat de fonctionner avec d'autres plugins Dalamud installés. Chaque intégration détecte automatiquement sa cible et se désactive silencieusement lorsque le plugin cible est absent.</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Saisie</value>
</data>
@@ -997,10 +895,7 @@
<value>Saisie et aperçu</value>
</data>
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Onglets tell automatiques</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
<value>Onglets de message privé automatiques</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Liens et infobulles</value>
@@ -1069,10 +964,10 @@
<value>Journal des modifications</value>
</data>
<data name="Settings_Chat_NotifyFailedTell_Name" xml:space="preserve">
<value>Notifier en cas de Tell échoué</value>
<value>Notifier en cas de Message privé échoué</value>
</data>
<data name="Settings_Chat_NotifyFailedTell_Description" xml:space="preserve">
<value>Affiche une notification lorsqu'un Tell que vous avez envoyé n'a pas pu être remis (destinataire hors ligne, dans une instance ou vous bloquant).</value>
<value>Affiche une notification lorsqu'un Message privé que vous avez envoyé n'a pas pu être remis (destinataire hors ligne, dans une instance ou vous bloquant).</value>
</data>
<data name="Settings_Chat_NotifyPluginDisclosure_Name" xml:space="preserve">
<value>Avertir avant d'envoyer des symboles réservés au plugin</value>
@@ -1138,12 +1033,332 @@
<value>Son Hellion</value>
</data>
<data name="FailedTell_Notification_Generic" xml:space="preserve">
<value>Un Tell n'a pas pu être remis.</value>
<value>Un Message privé n'a pas pu être remis.</value>
</data>
<data name="FailedTell_Notification_Named" xml:space="preserve">
<value>Le Tell à {0} n'a pas pu être remis.</value>
<value>Le Message privé à {0} n'a pas pu être remis.</value>
</data>
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Ce message contient des symboles réservés au plugin que d'autres joueurs pourraient voir comme des cases vides. Appuyez à nouveau sur Entrée pour envoyer quand même.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Insérer un symbole</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Paramètres</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Masquer le chat (Entrée pour le rouvrir)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Renvoyer cet onglet vers la fenêtre principale</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Une autre opération de base de données est en cours : {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>nettoyage de rétention</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>export</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>nettoyage</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>effacement de l'historique</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Le filtre de confidentialité est désactivé, donc chaque canal est enregistré et rien dans la base de données ne contredit vos réglages. Activez d'abord le filtre et choisissez des canaux.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Aucun canal n'est sélectionné, un nettoyage supprimerait donc tout l'historique. Choisissez les canaux à conserver, ou utilisez le bouton d'effacement si vous voulez vraiment tout supprimer.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>{0:N0} messages sont enregistrés. Si vous voulez en garder une copie, exportez-les avant d'effacer.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Maj : lance le nettoyage de rétention immédiatement au lieu d'attendre le passage quotidien. Supprime les messages plus anciens que les limites ci-dessus.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>L'effacement de l'historique a échoué. Rien n'a été supprimé, voir /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Télémétrie</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Aucune télémétrie n'est collectée. Le plugin n'envoie rien vous concernant ni sur votre utilisation.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Traduction automatique</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Aller au message le plus récent</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Insérer le marqueur de carte &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Insérer l'objet lié &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>désactivé</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Comportement</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Raccourcis clavier</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Notifications</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Modes d'affichage</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Historique</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Aide aux commandes</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Divulgation du plugin</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Mode de disposition</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Opacité</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Comportement de redimensionnement</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Ouverture automatique des messages privés</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Barre latérale</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Marque</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Liens</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Intégrations</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Crédits</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licence</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Cliquez sur un bouton, puis appuyez sur la combinaison de touches. Échap efface.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Passer à l'onglet suivant</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Passer à l'onglet précédent</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Changer reconstruit l'atlas de polices, le chat est donc vide un instant.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>Horloge 24 heures</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Afficher l'historique des sessions précédentes</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Désactivé, le journal démarre vide à chaque lancement et ne se remplit qu'avec les messages reçus ensuite.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Côté de l'aide aux commandes</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>De quel côté la liste de suggestions apparaît pendant la saisie.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Mode d'ouverture automatique des messages privés</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Où s'ouvre un message privé à son arrivée.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Basculer vers l'onglet à chaque message privé</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Sinon l'onglet s'ouvre en arrière-plan après le premier.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Barre latérale</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Onglets en haut</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Emplacement des onglets</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Où se place la liste d'onglets dans la fenêtre principale.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Afficher la barre de titre</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Afficher la barre de titre des fenêtres détachées</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Autoriser le déplacement</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Autoriser le redimensionnement</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Seuil de bascule automatique de la barre latérale</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>En dessous de cette largeur, la barre latérale se replie en onglets, en pixels.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Position de l'aperçu</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Afficher l'aperçu uniquement pendant la saisie</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Dépôt Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifeste du dépôt personnalisé</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Thème actif : {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Dupliquer et modifier</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Les thèmes intégrés ne peuvent pas être modifiés directement. Dupliquer crée une copie personnalisée que vous pouvez modifier et enregistrer.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Modifier le thème</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Modification : {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Surfaces</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Bordures</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Texte</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identité</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>État</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Enregistrer</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Annuler</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Réinitialiser à la source</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>La réinitialisation est indisponible pendant la modification d'une copie. Enregistrez ou annulez d'abord.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Enregistrez ou annulez vos modifications d'abord</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Personnalisés ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Dupliquer le thème actif</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importer un fichier de thème…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Chemin du fichier JSON (ou glissez-déposez dans le dossier)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Exporter le thème</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Froids</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturels</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Classiques</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Rétro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (incluse)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Police du jeu</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Globale : {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Actif : {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Écrivez un message...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Dupliquer</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>aperçu</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>maintenance</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} onglet</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} onglets</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} MP</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} MP</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} msg</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k msg</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Champion» Aperçu</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>ouvert</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Non connecté</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Plus d'actions</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Biztonsági háló azokhoz a ChatType-okhoz, amelyeket jövőbeli FFXIV-frissítések adnak hozzá, és a plugin még nem ismer. Az alapértelmezés KI (adatminimalizálás). Kapcsold be, ha a jövőbeli csatornákat is teljes egészében naplózni szeretnéd.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Szűrő alkalmazása a meglévő adatbázisra</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Az adatvédelmi szűrő csak az új üzenetekre hat. Az alábbi takarítással utólag eltávolíthatod a már tárolt üzeneteket, amelyek nem illeszkednek a mentett fehérlistádhoz.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>A takarítás a MENTETT fehérlistádat (Plugin.Config) használja, nem a fenti nem mentett módosításokat. Először kattints a Mentés gombra, ha az aktuális változtatásokat szeretnéd alkalmazni.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>A kézi futtatás a MENTETT megőrzési szabályzatot használja, nem a fenti csúszkák értékeit. Először kattints a Mentés gombra, ha a futtatásban az aktuális változtatásokat szeretnéd alkalmazni.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Az előnézet elavult: a fehérlistád megváltozott az utolsó frissítés óta. Kattints a Frissítés gombra az újraszámításhoz.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Megőrzés alkalmazása most</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: A megőrzési takarítást azonnal futtatja a MENTETT szabályzat alapján. Előbb mentsd el a módosításaidat.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Megőrzési takarítás fut a háttérben…</value>
</data>
@@ -184,7 +172,7 @@
<value>Válassz egy kezdő profilt. Mindent később is módosíthatsz a Beállítások → Adatvédelem menüpontban.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Adatminimalizálás (ajánlott)</value>
<value>Adatminimalizálás</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Csak a saját beszélgetéseid tárolódnak: tellek, party, FC, linkshellек, cross-world linkshellек, szövetség és ExtraChat. A nyilvános chat, az NPC-párbeszédek és a rendszerüzenetek a tárolás szintjén eldobódnak. A megőrzés a spec-alapértelmezettet követi (tellek 365 nap, saját csatornák 90 nap).</value>
@@ -226,7 +214,13 @@
<value>Üdvözöl a Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Egy Chat 2 fork a Hellion Forge-tól, adatvédelmet szem előtt tartó alapértelmezésekkel, egységes arculattal és néhány kényelmi funkcióval.</value>
<value>A te chatablakod a Hellion Forge-tól. Adatvédelem az első indítástól, 25 nyelven, és úgy rendezed be, ahogy szeretnéd.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>A Hellion Chat a Chat 2 forkjaként indult. A kettő azóta annyira eltávolodott egymástól, hogy a kódbázisok már nem kompatibilisek.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>A pluginek a Final Fantasy XIV-ben szürke zónát jelentenek: a Square Enix felhasználási feltételei nem terjednek ki rájuk, és Naoki Yoshida nyilvánosan kérte, hogy ne reklámozzák őket. Ne hozd tehát szóba a témát a Say, Yell, Shout és bármely más nyilvános csatornán.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Három rövid lépés. Mindent megváltoztathatsz később a Beállítások → Hellion Chat menüpontban.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Mi tárolódjon?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = a legtöbb játékosnak ajánlott.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Ajánlott</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Megjelenés</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Előző munkamenet betöltése indításkor</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Szűrők alkalmazása korábbi munkamenetek üzeneteire</value>
</data>
@@ -313,14 +304,11 @@
<value>(változatlan)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Próbáld ki: írj /tell &lt;Játékosnév&gt; a chatbe. A Hellion Chat automatikusan megnyit egy külön fület a beszélgetéshez, és előtölti az utolsó {0} üzenetet.</value>
<value>Próbáld ki: írj /tell &lt;Játékosnév&gt; a chatbe. A Hellion Chat automatikusan megnyit egy külön fület a beszélgetéshez, és előtölti az utolsó {0} üzenetet.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Beállítások → Hellion Chat a finomhangoláshoz</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Export (GDPR Art. 15 — Hozzáférési jog)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Tárolt üzenetek exportálása Markdown, JSON vagy CSV formátumban. Ezzel teljesíthetsz egy hozzáférési kérelmet attól a személytől, akinek az üzeneteit tároltad, vagy magaddal viheted a saját előzményeidet.</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 közösségi fordítók (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Aktív tellek</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Fül rögzítésének feloldása</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Előléptetés állandó füllé</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Ezt a TempTell-t normál füllé alakítja. A partnerhez való tell-kötés megszűnik: a fül ezentúl a csatornaszűrők alapján fogja az üzeneteket. Ha azt szeretnéd, hogy „a fül túlélje az újrabejelentkezést és kötve maradjon a partnerhez", inkább a Fül rögzítése funkciót használd.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>A rögzített fülek túlélik az újrabejelentkezést, és kötve maradnak a beszélgető partnerhez.</value>
</data>
@@ -504,7 +486,7 @@
<value>Rögzített: túléli az újrabejelentkezést.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Megjegyzés: Ha az XIV Messenger vagy egy hasonló plugin elnyomja a telleket, kapcsold ki ott a „Suppress DMs" opciót, hogy a Hellion Chat fogadhassa a telleket és megnyithassa az auto-füleket.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Tell-előzmények az auto-fülekben</value>
</data>
@@ -559,15 +541,9 @@
<value>Csak akkor lép életbe, ha az auto-tell-fülek be vannak kapcsolva a Chat fülön.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Beállítások átstrukturálva</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>A Hellion Chat 0.5.0 tematikus fülekbe rendezte a beállításokat. A chat-adatbázisod és az üzenettörténeted változatlan maradt. A beállítások visszaálltak az alapértelmezettekre. Ha újra ki szeretnéd választani az adatvédelmi profilodat, a Varázsló újra megnyitása gomb az Adatvédelem fülön található. Az előző konfiguráció biztonsági másolata HellionChat.json.pre-v10-backup néven található az aktív konfigurációs fájl mellett.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Általános</value>
</data>
@@ -590,9 +566,9 @@
<value>Névjegy</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Időbélyegek</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Ablakkeret</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Szimbólumválasztó gomb megjelenítése a chat-beviteli mező mellett</value>
</data>
@@ -621,23 +597,17 @@
<value>Egy kis gombot helyez a csatornajelző bal oldalára, amely egy FFXIV-ikonokat és válogatott szimbólumokat tartalmazó felugró ablakot nyit meg. Kapcsold ki, ha karcsúbb beviteli sort szeretnél.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Tárolás</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Áttekintés</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Karbantartás</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Rendszer</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emote-ok</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Ha több linkshellt használsz, a karbantartó azt javasolja, hogy minden shellnek legyen külön füle az áttekinthetőség érdekében. Másold le a fület, és minden másolatban szűkítsd a csatornaválasztást.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Fül ikonja</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>A chat-ablakot és az összes aktív pop-outot az elsődleges monitor bal felső sarkába helyezi vissza. Akkor hasznos, ha egy ablak a megjelenítési elrendezés megváltozása után (monitor lecsatlakoztatva, felbontás megváltozott) a látható területen kívülre kerül. A plugin munkamenetenként egyszer automatikus határellenőrzést is végez; ez a gomb a kézi menekülési útvonal, ha valami még így is elérhetetlenné válik.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Újdonság a v0.6.0-ban: most már közvetlenül a pop-outban is gépelhetsz. Kapcsold be a főkapcsolót az Ablak beállításokban.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Értettem</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Ablakbeállítások megnyitása</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Bármely chat-fület megnyithatod saját ablakként. Kattints az ablak ikonra a jobb felső sarokban, vagy jobb klikk a fülön. Újdonság a v0.6.1-ben: a pop-out bevitel alapértelmezés szerint aktív (kikapcsolható a Beállítások → Ablak alatt).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Értettem</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Beállítások megnyitása</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>A Hellion Chat nem indítható el, amíg a Chat 2 be van töltve.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Tiltsd le a Chat 2-t a /xlplugins-ban, majd engedélyezd újra a Hellion Chat-et.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Általános</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Nyelv, bevitel, hang és teljesítmény.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Megjelenés</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Ablak átlátszatlansága, betűtípusok, animáció</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Témák</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Témát választhatsz vagy importálhatod a sajátodat</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Ablak</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Mikor látható az ablak, és lehet-e mozgatni.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tellek, előnézet, üzenetviselkedés és emote-ok.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Fülek</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Egyéni chat-fülek létrehozása és konfigurálása.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Adatbázis</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Tárolás, migráció, régi adatok takarítása</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Névjegy</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Bővítmények, verzió, projektinformációk, fordítók és changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Témák</value>
</data>
@@ -803,7 +707,7 @@
<value>Megtartás</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Adatvédelem elöl</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Nyitott</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Adatok és adatvédelem</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Adatvédelmi szűrő, megőrzés, takarítás, export és adatbázis-statisztikák.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Speciális (Shift+kattintás a megnyitáshoz)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>A Hellion Chat 1.2.1 átrendezte a beállítások menüt és eltávolította a régi „Stílus felülbírálása" opciót (amelyet az 1.1.0-ban bevezetett témarendszer váltott fel). A többi beállításod változatlan maradt. Az ablak átlátszósága átkerült a „Theme &amp; Layout" menübe. Az előző konfiguráció biztonsági másolata a pluginConfigs/HellionChat.json.pre-v16-backup fájlban található az aktív HellionChat.json mellett.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>A plugin-integrációk lehetővé teszik, hogy a HellionChat más telepített Dalamud-pluginekkel együttműködjön. Minden integráció automatikusan felismeri a célpluginét, és csendesen letiltja magát, ha a célplugin hiányzik.</value>
</data>
@@ -955,7 +853,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Bevitel</value>
</data>
@@ -998,9 +896,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Automatikus tell lapfülek</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emote-ok</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Hivatkozások és súgóbubborékok</value>
</data>
@@ -1145,4 +1040,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Ez az üzenet plugin-kizárólagos szimbólumokat tartalmaz, amelyeket más játékosok üres négyzetként láthatnak. Nyomd meg ismét az Entert a küldéshez.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Szimbólum beszúrása</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Beállítások</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Csevegés elrejtése (Enter visszahozza)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Lap visszahelyezése a főablakba</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Már fut egy másik adatbázisművelet: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>megőrzési takarítás</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>exportálás</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>takarítás</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>az előzmények törlése</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Az adatvédelmi szűrő ki van kapcsolva, így minden csatorna mentésre kerül, és semmi sem mond ellent a beállításaidnak az adatbázisban. Előbb kapcsold be a szűrőt, és válassz csatornákat.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Nincs kiválasztva csatorna, így a takarítás a teljes előzményt törölné. Válaszd ki a megtartandó csatornákat, vagy használd a törlés gombot, ha tényleg mindent el akarsz távolítani.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>{0:N0} üzenet van elmentve. Ha meg akarsz tartani egy másolatot, törlés előtt exportáld őket.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: azonnal lefuttatja a megőrzési takarítást, nem várja meg a napi futást. Törli a fenti korlátoknál régebbi üzeneteket.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Az előzmények törlése nem sikerült. Semmi sem lett eltávolítva, lásd /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetria</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Nem gyűjtünk telemetriát. A bővítmény semmit sem küld rólad vagy a használatodról sehová.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Automatikus fordítás</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Ugrás a legutóbbi üzenetre</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Térképjelölő beszúrása &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Hivatkozott tárgy beszúrása &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>kikapcsolva</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Viselkedés</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Gyorsbillentyűk</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Értesítések</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Megjelenítési módok</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Előzmények</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Parancssúgó</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Bővítmény jelzése</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Elrendezési mód</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Átlátszatlanság</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Átméretezés</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Tell automatikus megnyitása</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Oldalsáv</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Márka</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Hivatkozások</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrációk</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Közreműködők</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licenc</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Kattints egy gombra, majd nyomd le a billentyűkombinációt. Az Esc törli.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Váltás a következő fülre</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Váltás az előző fülre</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>A váltás újraépíti a betűatlaszt, ezért a csevegés egy pillanatra kiürül.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24 órás óra</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Korábbi munkamenetek előzményeinek megjelenítése</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Kikapcsolva a napló minden indításkor üresen kezd, és csak az azóta érkezett üzenetekkel telik meg.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Parancssúgó oldala</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Melyik oldalon jelenik meg a parancslista gépelés közben.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Tell automatikus megnyitásának módja</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Hol nyílik meg egy tell, amikor megérkezik.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Váltás a fülre minden tellnél</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Egyébként a fül az első után a háttérben nyílik meg.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Oldalsáv</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Felső fülek</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Fülek elhelyezése</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Hol helyezkedik el a füllista a főablakban.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Címsor megjelenítése</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Címsor a pop-out ablakoknál</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Mozgatás engedélyezése</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Átméretezés engedélyezése</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Oldalsáv automatikus váltásának küszöbe</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>E szélesség alatt az oldalsáv felső fülekké alakul, képpontban.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Előnézet helye</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Előnézet csak gépelés közben</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea-tároló</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Egyéni tároló manifesztje</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Aktív téma: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Elágaztatás és szerkesztés</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>A beépített témák nem szerkeszthetők közvetlenül. Az elágaztatás egyéni másolatot hoz létre, amit szerkeszthetsz és menthetsz.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Téma szerkesztése</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Szerkesztés alatt: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Felületek</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Szegélyek</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Szöveg</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identitás</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Állapot</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Mentés</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Mégse</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Visszaállítás az eredetire</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Visszaállítás nem érhető el elágazás szerkesztése közben. Előbb ments vagy szakítsd meg.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Előbb mentsd vagy vesd el a módosításaidat</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Egyéni ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Aktív téma elágaztatása</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Témafájl importálása…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>A JSON-fájl útvonala (vagy húzd a mappába)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Téma exportálása</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Hűvös</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Természetes</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Klasszikus</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retró</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (mellékelt)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>A játék betűtípusa</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Globális: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Aktív: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Írj egy üzenetet...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Másolat</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>előnézet</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>karbantartás</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} lap</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} lap</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} suttogás</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} suttogás</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} üz.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k üz.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Bajnok» Előnézet</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>nyitva</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Nincs bejelentkezve</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>További műveletek</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Rete di sicurezza per i ChatType aggiunti da futuri aggiornamenti di FFXIV che il plugin non conosce ancora. Il predefinito è DISATTIVATO (minimizzazione dei dati). Attiva se vuoi che anche i canali futuri vengano registrati completamente.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Applica filtro al database esistente</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Il filtro privacy agisce solo sui nuovi messaggi. La pulizia qui sotto consente di rimuovere retroattivamente i messaggi già salvati che non corrispondono alla whitelist salvata.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>La pulizia usa la tua whitelist SALVATA (Plugin.Config), non le modifiche non salvate sopra. Clicca Salva prima se vuoi che le modifiche attuali vengano applicate.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>L'esecuzione manuale usa la tua policy di conservazione SALVATA, non i valori degli slider sopra. Clicca Salva prima se vuoi che l'esecuzione applichi le modifiche attuali.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Anteprima non aggiornata: la whitelist è cambiata dall'ultimo aggiornamento. Clicca Aggiorna per ricalcolare.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Applica conservazione ora</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Esegue immediatamente la pulizia della conservazione usando la policy SALVATA. Salva prima le modifiche.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Pulizia della conservazione in esecuzione in background…</value>
</data>
@@ -184,7 +172,7 @@
<value>Scegli un profilo di partenza. Puoi regolare tutto in seguito in Impostazioni → Privacy.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Minimizzazione dei dati (consigliata)</value>
<value>Minimizzazione dei dati</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Vengono salvate solo le tue conversazioni: tell, party, FC, linkshell, cross-world linkshell, alliance ed ExtraChat. La chat pubblica, i dialoghi NPC e lo spam di sistema vengono scartati a livello di archiviazione. La conservazione segue i valori predefiniti dello spec (tell 365 giorni, canali di conversazione propri 90 giorni).</value>
@@ -226,7 +214,13 @@
<value>Benvenuto in Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Un fork di Chat 2 da Hellion Forge con impostazioni predefinite attente alla privacy, un'estetica coerente con il brand e qualche miglioramento alla qualità della vita.</value>
<value>La tua finestra di chat, firmata Hellion Forge. Privacy fin da subito, tradotta in 25 lingue, e la sistemi come vuoi.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat è nato come fork di Chat 2. Da allora i due si sono allontanati al punto che le basi di codice non sono più compatibili.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>I plugin sono una zona grigia in Final Fantasy XIV: le condizioni d'uso di Square Enix non li contemplano, e Naoki Yoshida ha chiesto pubblicamente di non pubblicizzarli. Tieni quindi l'argomento fuori da Say, Yell, Shout e da ogni altro canale pubblico.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Tre brevi passaggi. Puoi cambiare tutto in seguito in Impostazioni → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Cosa viene salvato?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = consigliato per la maggior parte dei giocatori.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Consigliato</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Aspetto</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Carica la sessione precedente all'avvio</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Applica filtri ai messaggi delle sessioni precedenti</value>
</data>
@@ -313,14 +304,11 @@
<value>(invariato)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Provalo: digita /tell &lt;Nome Giocatore&gt; in chat. Hellion Chat apre un tab dedicato alla conversazione e precarica gli ultimi {0} messaggi.</value>
<value>Provalo: digita /tell &lt;Nome Giocatore&gt; in chat. Hellion Chat apre un tab dedicato alla conversazione e precarica gli ultimi {0} messaggi.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Impostazioni → Hellion Chat per regolazioni successive</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Esporta (GDPR Art. 15 — Diritto di accesso)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Esporta i messaggi salvati in Markdown, JSON o CSV. Puoi così soddisfare una richiesta di accesso da parte di una persona i cui messaggi hai conservato, o portare con te la tua cronologia.</value>
</data>
@@ -457,7 +445,7 @@
<value>Traduttori della community di Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Tell attivi</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Sblocca tab</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Converti in tab permanente</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Trasforma questo TempTell in un tab normale. Il legame tell con il partner viene rimosso: il tab catturerà i messaggi tramite i suoi filtri canale da ora in poi. Per "il tab sopravvive al relog restando legato a questo partner", usa Fissa tab.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>I tab fissi sopravvivono al relog e rimangono legati a questo partner di conversazione.</value>
</data>
@@ -504,7 +486,7 @@
<value>Fisso: sopravvive al relog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Nota: se XIV Messenger o un plugin simile sopprime i tell, disattiva lì l'opzione "Suppress DMs" in modo che Hellion Chat possa ricevere i tell e aprire i tab automatici.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Cronologia tell nei tab automatici</value>
</data>
@@ -559,15 +541,9 @@
<value>Ha effetto solo quando i tab tell automatici sono attivati nel tab Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Impostazioni ristrutturate</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 ha ristrutturato le impostazioni in tab tematici. Il database della chat e la cronologia dei messaggi rimangono invariati. Le impostazioni sono state ripristinate ai valori predefiniti. Se vuoi riselezionare il profilo privacy, il pulsante Riapri si trova nel tab Privacy. Un backup della configurazione precedente si trova in HellionChat.json.pre-v10-backup accanto al file di configurazione attivo.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Generale</value>
</data>
@@ -590,9 +566,9 @@
<value>Info</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Timestamp</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Cornice finestra</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Mostra pulsante selettore simboli accanto all'input della chat</value>
</data>
@@ -621,23 +597,17 @@
<value>Aggiunge un piccolo pulsante a sinistra dell'indicatore del canale che apre un popup con le icone FFXIV e un elenco di simboli selezionati. Disattiva se preferisci una barra di input più essenziale.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Archiviazione</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Panoramica</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Manutenzione</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Sistema</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Se usi più linkshell, il maintainer consiglia un tab per shell per una panoramica più ordinata. Duplica il tab e limita la selezione dei canali in ogni copia.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Icona tab</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Sposta la finestra della chat e tutti i pop-out attivi nell'angolo in alto a sinistra del monitor principale. Utile quando una finestra è finita fuori dall'area visibile dopo un cambio di layout del display (monitor scollegato, risoluzione cambiata). Il plugin esegue anche un controllo automatico dei limiti una volta per sessione; questo pulsante è la via di fuga manuale se qualcosa finisce comunque irraggiungibile.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Novità in v0.6.0: ora puoi digitare direttamente nei pop-out. Attiva l'interruttore principale nelle impostazioni Finestra.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Capito</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Apri impostazioni finestra</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Puoi aprire qualsiasi tab della chat come finestra separata. Clicca l'icona finestra in alto a destra o fai clic destro sul tab. Novità in v0.6.1: l'input nei pop-out è attivo per impostazione predefinita (disattivabile in Impostazioni → Finestra).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Capito</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Apri impostazioni</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat non può avviarsi mentre Chat 2 è caricato.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Disattiva Chat 2 in /xlplugins, poi riattiva Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Generale</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Lingua, input, audio e prestazioni.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Aspetto</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Opacità finestra, font, animazioni</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Scegli un theme o importa il tuo</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Finestra</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Quando la finestra è visibile e se può essere spostata.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tell, anteprima, comportamento messaggi ed emote.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Tab</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Crea e configura tab della chat personalizzati.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Database</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Archiviazione, migrazione, pulizia legacy</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Informazioni</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Estensioni, versione, informazioni sul progetto, traduttori e changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Mantieni</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Privacy prima</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Aperto</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Dati e privacy</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Filtro privacy, conservazione, pulizia, esportazione e statistiche database.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Avanzate (Shift+clic per aprire)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 ha riorganizzato il menu delle impostazioni e rimosso la vecchia opzione "Override style" (sostituita dal sistema theme dalla 1.1.0). Le impostazioni rimanenti sono invariate. La trasparenza della finestra è stata migrata in "Theme &amp; Layout". Un backup della configurazione precedente si trova in pluginConfigs/HellionChat.json.pre-v16-backup accanto al file HellionChat.json attivo.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Le integrazioni con plugin consentono a HellionChat di lavorare insieme ad altri plugin Dalamud installati. Ogni integrazione rileva automaticamente il suo target e si disattiva silenziosamente quando il plugin target è assente.</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Inserimento</value>
</data>
@@ -999,9 +897,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Schede tell automatiche</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Link e tooltip</value>
</data>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Questo messaggio contiene simboli esclusivi del plugin che altri giocatori potrebbero vedere come caselle vuote. Premi Invio di nuovo per inviare comunque.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Inserisci simbolo</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Impostazioni</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Nascondi la chat (Invio per riaprirla)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Riporta questa scheda nella finestra principale</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>È già in corso un'altra operazione sul database: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>pulizia di conservazione</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>esportazione</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>pulizia</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>cancellazione della cronologia</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Il filtro privacy è disattivato, quindi ogni canale viene salvato e nulla nel database contraddice le tue impostazioni. Attiva prima il filtro e scegli i canali.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Nessun canale è selezionato, quindi una pulizia cancellerebbe l'intera cronologia. Scegli i canali da conservare, oppure usa il pulsante di cancellazione se vuoi davvero eliminare tutto.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Ci sono {0:N0} messaggi salvati. Se vuoi conservarne una copia, esportali prima di cancellare.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: esegue subito la pulizia di conservazione invece di aspettare il passaggio giornaliero. Cancella i messaggi più vecchi dei limiti sopra.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>La cancellazione della cronologia non è riuscita. Non è stato rimosso nulla, vedi /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetria</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Non viene raccolta alcuna telemetria. Il plugin non invia nulla su di te o sul tuo utilizzo.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Traduzione automatica</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Vai al messaggio più recente</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Inserisci il segnalino mappa &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Inserisci l'oggetto collegato &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>disattivato</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Comportamento</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Scorciatoie</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Notifiche</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Modalità di visualizzazione</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Cronologia</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Aiuto comandi</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Avviso plugin</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Modalità di layout</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Opacità</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Ridimensionamento</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Apertura automatica dei tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Barra laterale</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Marchio</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Collegamenti</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrazioni</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Riconoscimenti</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licenza</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Fai clic su un pulsante, poi premi la combinazione di tasti. Esc cancella.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Passa alla scheda successiva</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Passa alla scheda precedente</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Il cambio ricostruisce l'atlante dei caratteri, quindi la chat resta vuota per un attimo.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>Orologio 24 ore</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Mostra la cronologia delle sessioni precedenti</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Disattivato, il registro parte vuoto a ogni avvio del gioco e si riempie solo con i messaggi ricevuti da quel momento.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Lato dell'aiuto comandi</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Su quale lato compare l'elenco dei suggerimenti mentre scrivi.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Modalità di apertura automatica dei tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Dove si apre un tell quando arriva.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Passa alla scheda a ogni tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Altrimenti la scheda si apre in secondo piano dopo il primo.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Barra laterale</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Schede in alto</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Posizione delle schede</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Dove si trova l'elenco delle schede nella finestra principale.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Mostra la barra del titolo</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Barra del titolo nei pop-out</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Consenti lo spostamento</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Consenti il ridimensionamento</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Soglia di passaggio barra laterale</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Sotto questa larghezza la barra laterale si ripiega in schede in alto, in pixel.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Posizione dell'anteprima</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Mostra l'anteprima solo durante la digitazione</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Repository Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifest del repository personalizzato</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Tema attivo: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Duplica e modifica</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>I temi integrati non si possono modificare direttamente. La duplicazione crea una copia personalizzata che puoi modificare e salvare.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Modifica tema</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Modifica di: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Superfici</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Bordi</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Testo</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identità</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Stato</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Salva</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Annulla</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Ripristina all'originale</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Il ripristino non è disponibile durante la modifica di una copia. Salva o annulla prima.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Salva o annulla prima le tue modifiche</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Personalizzati ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Duplica il tema attivo</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importa file tema…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Percorso del file JSON (o trascinalo nella cartella)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Esporta tema</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Freddi</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturali</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Classici</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (inclusa)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Carattere del gioco</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Globale: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Attivo: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Scrivi un messaggio...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplica</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>anteprima</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>manutenzione</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} scheda</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} schede</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} sussurro</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} sussurri</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} msg</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k msg</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Campione» Anteprima</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>aperto</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Non connesso</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Altre azioni</value>
</data>
</root>
+354 -139
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>将来の FFXIVパッチで追加されるプラグイン未対応の ChatType に対するセーフティネットです。デフォルトはオフ(データ最小化)。将来のチャンネルも完全に記録したい場合は有効にしてください。</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>既存データベースにフィルターを適用する</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>プライバシーフィルターは新しいメッセージにのみ適用されます。以下のクリーンアップを使用すると、保存済みのホワイトリストに一致しない既存のメッセージをさかのぼって削除できます。</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>クリーンアップには保存済みのホワイトリスト(Plugin.Config)が使用されます。上部の未保存の変更は反映されません。現在の変更を適用したい場合は、先に保存してください。</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>手動実行には保存済みの保持ポリシーが使用されます。上部のスライダーの値は反映されません。現在の変更を適用したい場合は、先に保存してください。</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>プレビューが古くなっています。前回の更新以降にホワイトリストが変更されました。「更新」をクリックして再計算してください。</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>保持期間をすぐに適用する</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: 保存済みのポリシーを使って保持期間のクリーンアップを即時実行します。先に変更を保存してください。</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>バックグラウンドで保持期間のクリーンアップを実行中…</value>
</data>
@@ -184,7 +172,7 @@
<value>開始プロファイルを選択してください。後で設定 → プライバシーからいつでも変更できます。</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>データ最小化(推奨)</value>
<value>データ最小化</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>自分の会話のみ保存されます: テル、パーティ、フリーカンパニー、リンクシェル、クロスワールドリンクシェル、アライアンス、ExtraChat。パブリックチャット、NPCの台詞、システムスパムはストレージレベルで破棄されます。保持期間は仕様デフォルト(テル 365日、自分の会話チャンネル 90日)に従います。</value>
@@ -226,7 +214,13 @@
<value>Hellion Chat へようこそ</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Hellion Forge による Chat 2 フォーク。プライバシーに配慮したデフォルト設定、ブランド一貫のビジュアル、そしていくつかの利便性向上機能を備えています。</value>
<value>Hellion Forge がお届けするチャットウィンドウ。初期設定からプライバシー重視、25言語対応、レイアウトは自由に組み替えられます。</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat は Chat 2 のフォークとして始まりました。その後、両者は大きく分かれ、コードベースはすでに互換性がありません。</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>ファイナルファンタジーXIVにおいてプラグインはグレーゾーンです。スクウェア・エニックスの利用規約は対象としておらず、吉田直樹氏も公の場で宣伝しないよう求めています。Say、Yell、Shout をはじめとする公開チャンネルでは話題にしないでください。</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>3つの短いステップです。後で設定 → Hellion Chat からすべて変更できます。</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>何が保存されますか?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = ほとんどのプレイヤーに推奨。</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>推奨</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>ロールプレイ</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>表示</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>起動時に前回のセッションを読み込む</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>以前のセッションのメッセージにもフィルターを適用する</value>
</data>
@@ -313,14 +304,11 @@
<value>(変更なし)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 試してみましょう: チャットに /tell &lt;プレイヤー名&gt; と入力してください。Hellion Chat が会話専用のタブを自動で開き、最新 {0} 件のメッセージをプリロードします。</value>
<value>試してみましょう: チャットに /tell &lt;プレイヤー名&gt; と入力してください。Hellion Chat が会話専用のタブを自動で開き、最新 {0} 件のメッセージをプリロードします。</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>設定 → Hellion Chat で後から細かく調整できます</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>エクスポート(GDPR Art. 15 — アクセス権)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>保存済みメッセージを Markdown、JSON、CSV 形式でエクスポートします。メッセージを保存した相手からのアクセス請求への対応や、自分の履歴を持ち出す際に活用できます。</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 コミュニティ翻訳者(アップストリーム)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>アクティブなテル</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>タブのピン留めを解除</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>永続タブに昇格</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>この TempTell を通常のタブに変換します。会話相手へのテル紐付けは解除され、以降はチャンネルフィルターでメッセージを受信します。「再ログイン後も残す + 相手との紐付けを維持」したい場合は「タブをピン留め」をご利用ください。</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>ピン留めされたタブは再ログイン後も残り、会話相手との紐付けを維持します。</value>
</data>
@@ -504,9 +486,9 @@
<value>ピン留め済み: 再ログイン後も残ります。</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
<value>オートテルタブ</value>
</data>
<data name="ChatLog_AutoTellTabs_Enable_Name" xml:space="preserve">
<value>/tell ごとに会話相手ごとのタブを自動で開く</value>
@@ -545,7 +527,7 @@
<value>注意: XIV Messenger や類似のプラグインがテルを抑制している場合、そちらの「Suppress DMs」オプションを無効にしてください。無効にすることで Hellion Chat がテルを受信し、自動タブを開けるようになります。</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>自動タブのテル履歴</value>
</data>
@@ -559,15 +541,9 @@
<value>チャットタブで自動テルタブが有効になっている場合にのみ適用されます。</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>設定が再構成されました</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 で設定がテーマ別タブに再構成されました。チャットデータベースとメッセージ履歴はそのまま保持されます。設定はデフォルト値にリセットされました。プライバシープロファイルを再選択したい場合は、プライバシータブの「再表示」ボタンをご利用ください。以前の設定のバックアップは、アクティブな設定ファイルの隣に HellionChat.json.pre-v10-backup として保存されています。</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>一般</value>
</data>
@@ -590,9 +566,9 @@
<value>情報</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>テーマ</value>
</data>
@@ -606,14 +582,14 @@
<value>タイムスタンプ</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>ウィンドウフレーム</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>チャット入力欄の隣にシンボルピッカーボタンを表示する</value>
</data>
@@ -621,23 +597,17 @@
<value>チャンネルインジケーターの左に小さなボタンを追加します。クリックすると FFXIV アイコンとシンボル一覧のポップアップが開きます。入力バーをシンプルにしたい場合は無効にしてください。</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>ストレージ</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>概要</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>メンテナンス</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>システム</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>エモート</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>フリーカンパニー</value>
</data>
@@ -654,7 +624,7 @@
<value>複数のリンクシェルを使用している場合、メンテナーはより整理された見通しのために各シェルに専用タブを作成することを推奨しています。タブを複製して各コピーのチャンネル選択を絞り込んでください。</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>タブアイコン</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>チャットウィンドウとすべてのアクティブなポップアウトをプライマリモニターの左上隅に戻します。ディスプレイレイアウトの変更(モニターの切断、解像度変更)後にウィンドウが表示領域外に移動した場合に便利です。プラグインはセッションごとに自動で境界チェックを行いますが、それでも届かない場合の手動での脱出手段としてこのボタンをご利用ください。</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>v0.6.0 の新機能: ポップアウト内で直接入力できるようになりました。ウィンドウ設定のマスタースイッチを有効にしてください。</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>了解</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>ウィンドウ設定を開く</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>どのチャットタブも独立したウィンドウとして開けます。右上のウィンドウアイコンをクリックするか、タブを右クリックしてください。v0.6.1 の新機能: ポップアウト入力がデフォルトで有効になりました(設定 → ウィンドウで無効にできます)。</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>了解</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>設定を開く</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Chat 2 が読み込まれている間は Hellion Chat を起動できません。</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>/xlplugins で Chat 2 を無効にしてから、Hellion Chat を再度有効にしてください。</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>一般</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>言語、入力、オーディオ、パフォーマンス。</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>外観</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>ウィンドウの不透明度、フォント、モーション</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>テーマ</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>テーマを選択するか、独自のテーマをインポートする</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>ウィンドウ</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>ウィンドウの表示タイミングと移動可否。</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>チャット</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>テル、プレビュー、メッセージの動作、エモート。</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>タブ</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>カスタムチャットタブの作成と設定。</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>データベース</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>ストレージ、移行、レガシーのクリーンアップ</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>概要</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>拡張機能、バージョン、プロジェクト情報、翻訳者、Changelog。</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>テーマ</value>
</data>
@@ -803,7 +707,7 @@
<value>保持</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>プライバシー優先</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>オープン</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>データとプライバシー</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>プライバシーフィルター、保持期間、クリーンアップ、エクスポート、データベース統計。</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>テーマ</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>詳細設定(Shift+クリックで開く)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 で設定メニューが整理され、古い「スタイルを上書き」オプションが削除されました(1.1.0 のテーマシステムに置き換えられました)。その他の設定は変更されていません。ウィンドウの透明度は「テーマ &amp; レイアウト」に移行されました。以前の設定のバックアップは、アクティブな HellionChat.json の隣に pluginConfigs/HellionChat.json.pre-v16-backup として保存されています。</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>プラグイン連携により、HellionChat は他のインストール済み Dalamud プラグインと連携できます。各連携は対象プラグインを自動で検出し、対象プラグインがない場合は静かに無効化されます。</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>入力</value>
</data>
@@ -997,10 +895,7 @@
<value>入力とプレビュー</value>
</data>
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>オートTellタブ</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>エモート</value>
<value>オートテルタブ</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>リンクとツールチップ</value>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>このメッセージにはプラグイン専用のシンボルが含まれており、他のプレイヤーには空白の箱として表示される可能性があります。Enterを再度押して送信します。</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>記号を挿入</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>設定</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>チャットを非表示(Enterで再表示)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>このタブをメインウィンドウに戻す</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>別のデータベース処理を実行中です: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>保存期間の整理</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>エクスポート</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>クリーンアップ</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>履歴の削除</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>プライバシーフィルターがオフのため、すべてのチャンネルが保存されており、設定と矛盾するデータはありません。まずフィルターをオンにしてチャンネルを選んでください。</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>チャンネルが一つも選ばれていないため、クリーンアップは履歴をすべて削除します。残したいチャンネルを選ぶか、本当にすべて消したい場合は削除ボタンを使ってください。</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>{0:N0} 件のメッセージが保存されています。控えを残したい場合は、削除する前にエクスポートしてください。</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: 毎日の処理を待たずに保存期間の整理をすぐ実行します。上の期限より古いメッセージを削除します。</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>履歴の削除に失敗しました。何も削除されていません。/xllog を確認してください。</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>テレメトリ</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>テレメトリは収集していません。あなたや利用状況に関する情報をどこにも送信しません。</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>定型文</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>最新のメッセージへ移動</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>マップフラグを挿入 &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>リンクしたアイテムを挿入 &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>オフ</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>動作</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>キー設定</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>通知</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>表示モード</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>履歴</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>コマンドヘルプ</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>プラグインの明示</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>レイアウトモード</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>不透明度</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>サイズ変更の動作</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>テルの自動オープン</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>サイドバー</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>ブランド</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>リンク</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>連携</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>クレジット</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>ライセンス</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>ボタンをクリックしてからキーの組み合わせを押してください。Esc で解除します。</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>次のチャットタブへ</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>前のチャットタブへ</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>切り替えるとフォントアトラスが再構築されるため、チャットが一瞬空になります。</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24時間表示</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>以前のセッションの履歴を表示</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>オフの場合、ログはゲーム起動のたびに空から始まり、それ以降に受信したメッセージだけが入ります。</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>コマンドヘルプの表示位置</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>入力中にコマンド候補をどちら側に表示するか。</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>テル自動オープンの方式</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>テルが届いたときにどこで開くか。</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>テルのたびにタブへ切り替える</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>そうでない場合、最初の 1 通のあとタブは背面で開きます。</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>サイドバー</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>上部タブ</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>タブの配置</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>メインウィンドウでタブ一覧をどこに置くか。</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>タイトルバーを表示</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>ポップアウトのタイトルバーを表示</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>移動を許可</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>サイズ変更を許可</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>サイドバー自動切り替えのしきい値</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>この幅を下回るとサイドバーが上部タブに折りたたまれます(ピクセル)。</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>プレビューの位置</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>入力中のみプレビューを表示</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea リポジトリ</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>カスタムリポジトリのマニフェスト</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>現在のテーマ: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>複製して編集</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>組み込みテーマは直接編集できません。複製すると、編集して保存できる独自のコピーが作られます。</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>テーマを編集</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>編集中: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>面</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>枠線</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>テキスト</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>アイデンティティ</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>ステータス</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>保存</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>キャンセル</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>元に戻す</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>複製を編集中はリセットできません。先に保存またはキャンセルしてください。</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>先に変更を保存または破棄してください</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>カスタム ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>現在のテーマを複製</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>テーマファイルをインポート…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSONファイルのパス(またはフォルダーにドラッグ&ドロップ)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>テーマをエクスポート</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>クール</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>ナチュラル</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>クラシック</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>レトロ</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter(同梱)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>ゲーム内フォント</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>全体: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>使用中: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>メッセージを入力...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>複製</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>プレビュー</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>メンテナンス</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} タブ</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} タブ</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} テル</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} テル</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} 件</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k 件</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Champion» プレビュー</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>開いています</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>未ログイン</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>その他の操作</value>
</data>
</root>
+354 -139
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>향후 FFXIV 패치로 추가될 수 있는 미지의 ChatType에 대한 안전장치입니다. 기본값은 꺼짐 (데이터 최소화)입니다. 향후 채널도 완전히 기록하고 싶다면 활성화하세요.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>기존 데이터베이스에 필터 적용</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>개인정보 필터는 새 메시지에만 적용됩니다. 아래 정리 기능을 사용하면 저장된 화이트리스트에 맞지 않는 기존 메시지를 소급하여 삭제할 수 있습니다.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>정리 작업은 위의 미저장 변경사항이 아닌 저장된 화이트리스트 (Plugin.Config)를 사용합니다. 현재 변경사항을 적용하려면 먼저 저장하세요.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>수동 실행은 위의 슬라이더 값이 아닌 저장된 보존 정책을 사용합니다. 현재 변경사항을 적용하려면 먼저 저장하세요.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>미리보기가 오래되었습니다. 마지막 새로 고침 이후 화이트리스트가 변경되었습니다. 새로 고침을 클릭하여 다시 계산하세요.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>지금 보존 정책 적용</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: 저장된 정책으로 보존 정리를 즉시 실행합니다. 먼저 변경사항을 저장하세요.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>백그라운드에서 보존 정리 작업 중…</value>
</data>
@@ -184,7 +172,7 @@
<value>시작 프로필을 선택하세요. 나중에 설정 → 개인정보에서 모두 조정할 수 있습니다.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>데이터 최소화 (권장)</value>
<value>데이터 최소화</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>자신의 대화만 저장됩니다. 귓속말, 파티, 자유부대, 링크셸, 서버 초월 링크셸, 연합 파티, ExtraChat이 포함됩니다. 공개 채팅, NPC 대화, 시스템 스팸은 저장 단계에서 제외됩니다. 보존 기간은 기본 스펙을 따릅니다 (귓속말 365일, 개인 대화 채널 90일).</value>
@@ -226,7 +214,13 @@
<value>Hellion Chat에 오신 것을 환영합니다</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Hellion Forge에서 만든 Chat 2 포크입니다. 개인정보 보호 기본값, 브랜드 일관성 있는 디자인, 그리고 몇 가지 편의 기능을 제공합니다.</value>
<value>Hellion Forge가 만든 채팅 창입니다. 기본값부터 개인정보 우선, 25개 언어 지원, 배치는 원하는 대로.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat은 Chat 2의 포크로 시작했습니다. 그 뒤로 둘은 코드베이스가 더 이상 호환되지 않을 만큼 멀어졌습니다.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>파이널 판타지 XIV에서 플러그인은 회색 지대입니다. 스퀘어 에닉스 이용약관은 이를 다루지 않으며, 요시다 나오키는 공개적으로 홍보하지 말아 달라고 요청했습니다. 말하기, 떠들기, 외치기를 비롯한 모든 공개 채널에서는 이 주제를 꺼내지 마세요.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>세 가지 간단한 단계입니다. 나중에 설정 → Hellion Chat에서 모두 변경할 수 있습니다.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>무엇을 저장할까요?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = 대부분의 플레이어에게 권장됩니다.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>권장</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>롤플레이</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>시각적 설정</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>시작 시 이전 세션 불러오기</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>이전 세션 메시지에 필터 적용</value>
</data>
@@ -313,14 +304,11 @@
<value>(변경 없음)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 테스트해보세요. 채팅창에 /tell &lt;Player Name&gt;을 입력하면 Hellion Chat이 대화를 위한 전용 탭을 열고 마지막 {0}개의 메시지를 미리 불러옵니다.</value>
<value>테스트해보세요. 채팅창에 /tell &lt;Player Name&gt;을 입력하면 Hellion Chat이 대화를 위한 전용 탭을 열고 마지막 {0}개의 메시지를 미리 불러옵니다.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>나중에 세부 조정은 설정 → Hellion Chat에서</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>내보내기 (GDPR Art. 15 — 열람권)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>저장된 메시지를 Markdown, JSON, 또는 CSV 형식으로 내보냅니다. 저장된 메시지의 당사자가 열람을 요청하거나 자신의 기록을 가져갈 때 사용할 수 있습니다.</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 커뮤니티 번역자 (업스트림)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>활성 귓속말</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>탭 고정 해제</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>영구 탭으로 변환</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>이 임시 귓속말 탭을 일반 탭으로 변환합니다. 상대방과의 귓속말 연결이 해제되며, 이후 채널 필터로 메시지를 받습니다. "재접속 후에도 상대방과 연결 유지"를 원한다면 탭 고정을 사용하세요.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>고정된 탭은 재접속 후에도 유지되며 이 대화 상대와의 연결이 유지됩니다.</value>
</data>
@@ -504,9 +486,9 @@
<value>고정됨: 재접속 후에도 유지됩니다.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
<value>자동 귓속말 탭</value>
</data>
<data name="ChatLog_AutoTellTabs_Enable_Name" xml:space="preserve">
<value>모든 /tell에 대해 대화 상대별 탭 자동 열기</value>
@@ -545,7 +527,7 @@
<value>참고: XIV Messenger 또는 유사한 플러그인이 귓속말을 차단하는 경우 해당 플러그인의 "Suppress DMs" 옵션을 비활성화해야 Hellion Chat이 귓속말을 받고 자동 탭을 열 수 있습니다.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>자동 탭의 귓속말 기록</value>
</data>
@@ -559,15 +541,9 @@
<value>채팅 탭에서 자동 귓속말 탭이 활성화된 경우에만 적용됩니다.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>설정이 재구성되었습니다</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0에서 설정이 주제별 탭으로 재구성되었습니다. 채팅 데이터베이스와 메시지 기록은 변경되지 않았습니다. 설정이 기본값으로 초기화되었습니다. 개인정보 프로필을 다시 선택하려면 개인정보 탭의 다시 열기 버튼을 사용하세요. 이전 설정의 백업이 활성 설정 파일 옆에 HellionChat.json.pre-v10-backup으로 저장되어 있습니다.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>일반</value>
</data>
@@ -590,9 +566,9 @@
<value>정보</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>테마</value>
</data>
@@ -606,14 +582,14 @@
<value>타임스탬프</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>창 프레임</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>채팅 입력창 옆에 기호 선택기 버튼 표시</value>
</data>
@@ -621,23 +597,17 @@
<value>채널 표시기 왼쪽에 작은 버튼을 추가합니다. 클릭하면 FFXIV 아이콘과 엄선된 기호 목록이 있는 팝업이 열립니다. 입력창을 간결하게 유지하려면 비활성화하세요.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>저장소</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>개요</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>유지 관리</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>시스템</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>감정 표현</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>자유부대</value>
</data>
@@ -654,7 +624,7 @@
<value>링크셸을 여러 개 사용한다면 관리자는 각 셸마다 탭 하나를 사용하여 더 깔끔한 개요를 유지할 것을 권장합니다. 탭을 복제하고 각 복사본에서 채널 선택을 제한하세요.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>탭 아이콘</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>채팅 창과 모든 활성 팝아웃을 기본 모니터의 왼쪽 상단 모서리로 이동합니다. 디스플레이 레이아웃 변경 (모니터 분리, 해상도 변경) 후 창이 화면 밖으로 벗어났을 때 유용합니다. 플러그인은 세션당 한 번 자동 경계 검사를 수행하며, 이 버튼은 그래도 접근할 수 없는 경우를 위한 수동 탈출구입니다.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>v0.6.0의 새 기능: 이제 팝아웃에서 직접 입력할 수 있습니다. 창 설정에서 마스터 스위치를 활성화하세요.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>확인</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>창 설정 열기</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>모든 채팅 탭을 별도 창으로 열 수 있습니다. 오른쪽 상단의 창 아이콘을 클릭하거나 탭을 우클릭하세요. v0.6.1의 새 기능: 팝아웃 입력이 기본으로 활성화되었습니다 (설정 → 창에서 비활성화 가능).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>확인</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>설정 열기</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Chat 2가 로드된 상태에서는 Hellion Chat을 시작할 수 없습니다.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>/xlplugins에서 Chat 2를 비활성화한 후 Hellion Chat을 다시 활성화하세요.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>일반</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>언어, 입력, 오디오, 성능.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>외형</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>창 불투명도, 글꼴, 모션.</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>테마</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>테마 선택 또는 가져오기</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>창</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>창의 표시 조건 및 이동 가능 여부.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>채팅</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>귓속말, 미리보기, 메시지 동작, 감정 표현.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>탭</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>사용자 정의 채팅 탭 생성 및 설정.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>데이터베이스</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>저장소, 마이그레이션, 레거시 정리.</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>소개</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>확장 기능, 버전, 프로젝트 정보, 번역자, Changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>테마</value>
</data>
@@ -803,7 +707,7 @@
<value>유지</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>개인정보 우선</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>전체 공개</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>데이터 및 개인 정보</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>개인 정보 필터, 보존, 정리, 내보내기, 데이터베이스 통계.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>테마</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>고급 설정 (Shift+클릭으로 열기)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1에서 설정 메뉴가 재구성되었으며 기존 "스타일 재정의" 옵션이 제거되었습니다 (1.1.0의 테마 시스템으로 대체됨). 나머지 설정은 변경되지 않았습니다. 창 투명도는 "테마 &amp; 레이아웃"으로 이전되었습니다. 이전 설정의 백업이 활성 HellionChat.json 옆에 pluginConfigs/HellionChat.json.pre-v16-backup으로 저장되어 있습니다.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>플러그인 연동을 통해 HellionChat은 설치된 다른 Dalamud 플러그인과 함께 작동합니다. 각 연동은 대상 플러그인을 자동으로 감지하며, 대상 플러그인이 없으면 자동으로 비활성화됩니다.</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>입력</value>
</data>
@@ -997,10 +895,7 @@
<value>입력 및 미리 보기</value>
</data>
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>자동 텔 탭</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>감정 표현</value>
<value>자동 귓속말 탭</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>링크 및 툴팁</value>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>이 메시지에는 다른 플레이어에게 빈 박스로 보일 수 있는 플러그인 전용 기호가 포함되어 있습니다. Enter를 다시 눌러 전송합니다.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>기호 삽입</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>설정</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>채팅 숨기기 (Enter로 다시 표시)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>이 탭을 기본 창으로 되돌리기</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>다른 데이터베이스 작업이 실행 중입니다: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>보존 기간 정리</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>내보내기</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>정리</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>기록 삭제</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>개인정보 필터가 꺼져 있어 모든 채널이 저장되며, 데이터베이스에 설정과 어긋나는 내용이 없습니다. 먼저 필터를 켜고 채널을 선택하세요.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>선택된 채널이 없어 정리를 실행하면 기록 전체가 삭제됩니다. 남길 채널을 선택하거나, 정말 모두 지우려면 삭제 버튼을 사용하세요.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>{0:N0}개의 메시지가 저장되어 있습니다. 사본을 남기려면 삭제하기 전에 내보내세요.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: 매일 실행을 기다리지 않고 보존 기간 정리를 지금 실행합니다. 위 기한보다 오래된 메시지를 삭제합니다.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>기록 삭제에 실패했습니다. 아무것도 삭제되지 않았습니다. /xllog를 확인하세요.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>원격 측정</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>원격 측정 정보를 수집하지 않습니다. 사용자나 사용 내역에 관한 어떤 정보도 전송하지 않습니다.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>정형문</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>최신 메시지로 이동</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>지도 표시 삽입 &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>연결된 아이템 삽입 &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>끔</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>동작</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>단축키</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>알림</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>표시 모드</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>기록</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>명령어 도움말</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>플러그인 고지</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>레이아웃 모드</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>불투명도</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>크기 조절 동작</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>귓속말 자동 열기</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>사이드바</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>브랜드</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>링크</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>연동</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>제작 정보</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>라이선스</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>버튼을 클릭한 뒤 키 조합을 누르세요. Esc로 지웁니다.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>다음 채팅 탭으로</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>이전 채팅 탭으로</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>전환하면 폰트 아틀라스를 다시 만들기 때문에 채팅이 잠시 비워집니다.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24시간제</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>이전 세션의 기록 표시</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>끄면 게임을 실행할 때마다 기록이 비어 있는 상태로 시작하고, 이후 받은 메시지만 채워집니다.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>명령어 도움말 위치</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>입력 중에 명령어 힌트 목록을 어느 쪽에 표시할지.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>귓속말 자동 열기 방식</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>귓속말이 도착했을 때 어디에서 열릴지.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>귓속말마다 탭으로 전환</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>그렇지 않으면 첫 통 이후 탭이 배경에서 열립니다.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>사이드바</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>상단 탭</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>탭 배치</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>메인 창에서 탭 목록의 위치.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>제목 표시줄 보이기</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>팝아웃 창의 제목 표시줄 보이기</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>이동 허용</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>크기 조절 허용</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>사이드바 자동 전환 임계값</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>이 너비 미만이면 사이드바가 상단 탭으로 접힙니다(픽셀).</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>미리보기 위치</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>입력 중에만 미리보기 표시</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea 저장소</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>커스텀 저장소 매니페스트</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>현재 테마: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>복제 후 편집</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>기본 제공 테마는 직접 편집할 수 없습니다. 복제하면 편집하고 저장할 수 있는 사용자 테마가 만들어집니다.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>테마 편집</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>편집 중: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>표면</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>테두리</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>텍스트</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>아이덴티티</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>상태</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>저장</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>취소</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>원본으로 되돌리기</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>복제본을 편집하는 동안에는 되돌릴 수 없습니다. 먼저 저장하거나 취소하세요.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>먼저 변경 사항을 저장하거나 취소하세요</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>사용자 지정 ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>현재 테마 복제</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>테마 파일 가져오기…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSON 파일 경로 (또는 폴더로 끌어다 놓기)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>테마 내보내기</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>쿨</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>내추럴</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>클래식</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>레트로</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (기본 포함)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>게임 글꼴</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>전역: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>사용 중: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>메시지를 입력하세요...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>복제</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>미리보기</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>유지 관리</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} 탭</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} 탭</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} 귓속말</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} 귓속말</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} 개</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k 개</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Champion» 미리보기</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>열림</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>로그인되지 않음</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>추가 작업</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Sikkerhetsnett for ChatTypes som legges til av fremtidige FFXIV-oppdateringer som pluginen ennå ikke kjenner til. Standard er AV (dataminimering). Aktiver om du vil at fremtidige kanaler også skal logges fullstendig.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Bruk filter på eksisterende database</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Personvernfilteret påvirker bare nye meldinger. Oppryddingen nedenfor lar deg fjerne allerede lagrede meldinger som ikke samsvarer med den lagrede hvitelisten din.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Oppryddingen bruker den LAGREDE hvitelisten din (Plugin.Config), ikke ulagrede endringer ovenfor. Klikk Lagre først om du vil at de nåværende endringene skal brukes.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Den manuelle kjøringen bruker den LAGREDE oppbevaringspolicyen din, ikke skyveknappverdiene ovenfor. Klikk Lagre først om du vil at kjøringen skal bruke de nåværende endringene.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Forhåndsvisningen er utdatert: hvitelisten din har endret seg siden siste oppdatering. Klikk Oppdater for å beregne på nytt.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Bruk oppbevaring nå</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Kjører oppbevaringsoppryddingen umiddelbart med den LAGREDE policyen. Lagre endringene dine først.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Oppbevaringsopprydding kjører i bakgrunnen…</value>
</data>
@@ -184,7 +172,7 @@
<value>Velg en startprofil. Du kan justere alt senere under Innstillinger → Personvern.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Dataminimering (anbefalt)</value>
<value>Dataminimering</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Bare dine egne samtaler lagres: tells, party, FC, linkshells, cross-world linkshells, alliance og ExtraChat. Offentlig chat, NPC-dialoger og systemspam forkastes på lagringsnivå. Oppbevaring følger spec-standarder (tells 365 dager, egne samtalekanaler 90 dager).</value>
@@ -226,7 +214,13 @@
<value>Velkommen til Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>En Chat 2-fork fra Hellion Forge med personvernvennlige standarder, merkevarekonsekvente visuals og noen livskvalitetsforbedringer.</value>
<value>Chatvinduet ditt fra Hellion Forge. Personvern fra første start, 25 språk, og du setter det opp slik du vil.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat startet som en fork av Chat 2. De to har siden fjernet seg så mye fra hverandre at kodebasene ikke lenger er kompatible.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Plugins er en gråsone i Final Fantasy XIV: Square Enix' bruksvilkår dekker dem ikke, og Naoki Yoshida har offentlig bedt om at man ikke reklamerer for dem. Hold derfor temaet unna Say, Yell, Shout og alle andre offentlige kanaler.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Tre korte steg. Du kan endre alt senere under Innstillinger → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Hva blir lagret?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = anbefalt for de fleste spillere.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Anbefalt</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Utseende</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Last inn forrige økt ved oppstart</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Bruk filtre på meldinger fra tidligere økter</value>
</data>
@@ -313,14 +304,11 @@
<value>(uendret)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Prøv det: skriv /tell &lt;Spillernavn&gt; i chatten. Hellion Chat åpner en dedikert fane for samtalen og forhåndslaster de siste {0} meldingene.</value>
<value>Prøv det: skriv /tell &lt;Spillernavn&gt; i chatten. Hellion Chat åpner en dedikert fane for samtalen og forhåndslaster de siste {0} meldingene.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Innstillinger → Hellion Chat for å finjustere senere</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Eksport (GDPR Art. 15 — Rett til innsyn)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Eksporter lagrede meldinger som Markdown, JSON eller CSV. Dette lar deg oppfylle en innsynsforespørsel fra en person hvis meldinger du har lagret, eller ta med deg din egen historikk.</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 fellesskapsoversetterne (oppstrøms)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Aktive tells</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Løsgjør fane</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Gjør permanent</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Gjør denne TempTell om til en vanlig fane. Tell-bindingen til samtalepartneren fjernes, og fanen vil fra nå av fange meldinger via kanalfilteret. For å overleve relog mens du forblir bundet til denne partneren, bruk Fest fane i stedet.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Festede faner overlever relog og forblir bundet til denne samtalepartneren.</value>
</data>
@@ -504,7 +486,7 @@
<value>Festet: overlever relog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Merk: Hvis XIV Messenger eller et lignende plugin undertrykker tells, deaktiver "Suppress DMs"-alternativet der slik at Hellion Chat kan motta tells og åpne auto-fanene.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Tell-historikk i auto-faner</value>
</data>
@@ -559,15 +541,9 @@
<value>Gjelder bare når auto-tell-faner er aktivert i Chat-fanen.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Innstillinger omstrukturert</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 har omstrukturert innstillingene i tematiske faner. Chat-databasen og meldingshistorikken din er uendret. Innstillinger har blitt tilbakestilt til standardverdier. Hvis du vil velge personvernprofil på nytt, finner du Åpne igjen-knappen i Personvern-fanen. En sikkerhetskopi av forrige konfig ligger på HellionChat.json.pre-v10-backup ved siden av den aktive konfig-filen.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Generelt</value>
</data>
@@ -590,9 +566,9 @@
<value>Om</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Tidsstempler</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Vindusramme</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Vis symbolvelger-knapp ved siden av chat-inndata</value>
</data>
@@ -621,23 +597,17 @@
<value>Legger til en liten knapp til venstre for kanalindikatoren som åpner et popup-vindu med FFXIV-ikoner og en kuratert symbolliste. Deaktiver for en slankere inndatalinje.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Lagring</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Oversikt</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Vedlikehold</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>System</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Hvis du bruker flere linkshells, anbefaler vedlikeholderen én fane per shell for en ryddigere oversikt. Dupliser fanen og begrens kanalvalget i hver kopi.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Fane-ikon</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Flytter chat-vinduet og alle aktive pop-out-vinduer tilbake til øverste venstre hjørne på primærskjermen. Nyttig når et vindu har havnet utenfor det synlige området etter en endring i skjermoppsettet (skjerm koblet fra, oppløsning endret). Pluginen utfører også en automatisk grensekontroll én gang per økt. Denne knappen er den manuelle nødutgangen hvis noe likevel havner utenfor rekkevidde.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Nytt i v0.6.0: Du kan nå skrive direkte i pop-out-vinduer. Aktiver hovedbryteren i Vindu-innstillingene.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Forstått</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Åpne vindusinnstillinger</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Du kan åpne hvilken som helst chat-fane som sitt eget vindu. Klikk vindusikonet øverst til høyre eller høyreklikk fanen. Nytt i v0.6.1: pop-out-inndata er aktiv som standard (kan deaktiveres under Innstillinger → Vindu).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Forstått</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Åpne innstillinger</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat kan ikke starte mens Chat 2 er lastet.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Deaktiver Chat 2 i /xlplugins, aktiver deretter Hellion Chat på nytt.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Generelt</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Språk, inndata, lyd og ytelse.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Utseende</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Vindusopasitet, skrifttyper, bevegelse</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Velg et theme eller importer ditt eget</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Vindu</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Når vinduet er synlig og om det kan flyttes.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, forhåndsvisning, meldingsoppførsel og emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Faner</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Opprett og konfigurer egendefinerte chat-faner.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Database</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Lagring, migrering, eldre opprydding</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Om</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Utvidelser, versjon, prosjektinformasjon, oversettere og changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Behold</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Personvern først</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Åpen</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Data og personvern</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Personvernfilter, oppbevaring, opprydding, eksport og databasestatistikk.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Avansert (Shift+klikk for å åpne)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 har reorganisert innstillingsmenyen og fjernet det gamle "Overstyr stil"-alternativet (erstattet av theme-systemet fra 1.1.0). Øvrige innstillinger er uendret. Vindustransparens er migrert til "Theme &amp; Layout". En sikkerhetskopi av forrige konfig ligger under pluginConfigs/HellionChat.json.pre-v16-backup ved siden av den aktive HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Plugin-integrasjoner lar HellionChat samarbeide med andre installerte Dalamud-plugins. Hver integrasjon oppdager automatisk målet sitt og deaktiverer seg stille når mål-pluginen mangler.</value>
</data>
@@ -955,7 +853,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Input</value>
</data>
@@ -998,9 +896,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Automatiske tell-faner</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Lenker og verktøytips</value>
</data>
@@ -1145,4 +1040,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Denne meldingen inneholder plugin-eksklusive symboler som andre spillere kanskje ser som tomme bokser. Trykk Enter igjen for å sende likevel.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Sett inn symbol</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Innstillinger</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Skjul chatten (Enter henter den tilbake)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Send denne fanen tilbake til hovedvinduet</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>En annen databaseoperasjon kjører: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>oppbevaringsopprydding</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>eksport</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>opprydding</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>sletting av historikken</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Personvernfilteret er av, så alle kanaler lagres, og ingenting i databasen strider mot innstillingene dine. Slå på filteret og velg kanaler først.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Ingen kanal er valgt, så en opprydding ville slette hele historikken. Velg kanalene du vil beholde, eller bruk sletteknappen hvis du virkelig vil fjerne alt.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>{0:N0} meldinger er lagret. Vil du beholde en kopi, eksporter dem før du sletter.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: kjører oppryddingen med en gang i stedet for å vente på det daglige gjennomløpet. Sletter meldinger eldre enn grensene over.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Sletting av historikken mislyktes. Ingenting ble fjernet, se /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetri</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Ingen telemetri samles inn. Dette pluginet sender ingenting om deg eller bruken din noe sted.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Auto-oversettelse</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Hopp til den nyeste meldingen</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Sett inn kartmarkør &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Sett inn lenket gjenstand &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>av</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Oppførsel</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Hurtigtaster</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Varsler</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Visningsmoduser</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Historikk</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Kommandohjelp</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Plugin-varsel</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Oppsettsmodus</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Dekkevne</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Størrelsesendring</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Automatisk åpning av tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Sidepanel</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Merke</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Lenker</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrasjoner</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Bidragsytere</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Lisens</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Klikk på en knapp, og trykk deretter tastekombinasjonen. Esc tømmer.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Bytt til neste fane</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Bytt til forrige fane</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Bytte bygger fontatlaset på nytt, så chatten er tom et øyeblikk.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24-timers klokke</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Vis historikk fra tidligere økter</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Av betyr at loggen starter tom hver gang spillet startes, og bare fylles med meldinger mottatt etterpå.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Side for kommandohjelp</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Hvilken side listen med kommandotips vises på mens du skriver.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Modus for automatisk åpning av tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Hvor en tell åpnes når den kommer.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Bytt til fanen ved hver tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Ellers åpnes fanen i bakgrunnen etter den første.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Sidepanel</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Faner øverst</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Plassering av faner</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Hvor fanelisten sitter i hovedvinduet.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Vis tittellinje</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Tittellinje for pop-out-vinduer</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Tillat flytting</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Tillat størrelsesendring</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Terskel for automatisk bytte av sidepanel</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Under denne bredden brettes sidepanelet til faner øverst, i piksler.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Plassering av forhåndsvisning</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Vis forhåndsvisning bare under skriving</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea-repositorium</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifest for egendefinert repo</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Aktivt tema: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Forgrein og rediger</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Innebygde temaer kan ikke redigeres direkte. Forgrening lager en egen kopi du kan redigere og lagre.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Rediger tema</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Redigerer: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Flater</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Kanter</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Tekst</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identitet</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Status</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Lagre</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Avbryt</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Tilbakestill til kilden</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Tilbakestilling er ikke tilgjengelig mens du redigerer en forgrening. Lagre eller avbryt først.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Lagre eller forkast endringene dine først</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Egendefinerte ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Forgrein aktivt tema</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importer temafil…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Sti til JSON-fil (eller dra og slipp i mappen)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Eksporter tema</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Kjølige</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturlige</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Klassiske</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (medfølger)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Spillets skrift</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Global: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Aktiv: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Skriv en melding...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Dupliser</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>forhåndsvisning</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>vedlikehold</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} fane</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} faner</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} tell</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} tells</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} meld.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k meld.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Champion» Forhåndsvisning</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>åpen</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Ikke innlogget</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Flere handlinger</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Vangnet voor ChatTypes die via toekomstige FFXIV-patches worden toegevoegd en nog niet bekend zijn bij de plugin. Standaard is UIT (dataminimalisatie). Schakel in als je toekomstige kanalen ook volledig wilt loggen.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Filter toepassen op bestaande database</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Het privacyfilter heeft alleen invloed op nieuwe berichten. Met de opschoning hieronder kun je reeds opgeslagen berichten alsnog verwijderen die niet overeenkomen met je opgeslagen whitelist.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>De opschoning gebruikt je OPGESLAGEN whitelist (Plugin.Config), niet de niet-opgeslagen wijzigingen hierboven. Klik eerst op Opslaan als je wilt dat je huidige wijzigingen worden toegepast.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>De handmatige uitvoering gebruikt je OPGESLAGEN retentiebeleid, niet de sliderwaarden hierboven. Klik eerst op Opslaan als je wilt dat de uitvoering je huidige wijzigingen toepast.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Voorbeeld is verouderd: je whitelist is gewijzigd sinds de laatste vernieuwing. Klik op Vernieuwen om opnieuw te berekenen.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Retentie nu toepassen</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Voert de retentieopschoning onmiddellijk uit met het OPGESLAGEN beleid. Sla je wijzigingen eerst op.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Retentieopschoning wordt op de achtergrond uitgevoerd…</value>
</data>
@@ -184,7 +172,7 @@
<value>Kies een startprofiel. Je kunt later alles aanpassen via Instellingen → Privacy.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Dataminimalisatie (aanbevolen)</value>
<value>Dataminimalisatie</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Alleen je eigen gesprekken worden opgeslagen: tells, groep, FC, linkshells, cross-world linkshells, alliantie en ExtraChat. Openbare chat, NPC-dialogen en systeemspam worden op opslagniveau verwijderd. Retentie volgt spec-standaarden (tells 365 dagen, eigen gesprekkanalen 90 dagen).</value>
@@ -226,7 +214,13 @@
<value>Welkom bij Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Een Chat 2 fork van Hellion Forge met privacybewuste standaarden, merkconforme uitstraling en handige quality-of-life verbeteringen.</value>
<value>Jouw chatvenster van Hellion Forge. Privacy vanaf de eerste start, in 25 talen, en je richt het in zoals jij wilt.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat begon als een fork van Chat 2. De twee zijn sindsdien zo ver uit elkaar gegroeid dat de codebases niet meer compatibel zijn.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Plugins zijn in Final Fantasy XIV een grijs gebied: de gebruiksvoorwaarden van Square Enix dekken ze niet, en Naoki Yoshida heeft publiekelijk gevraagd er geen reclame voor te maken. Houd het onderwerp dus buiten Zeg, Roep, Schreeuw en elk ander openbaar kanaal.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Drie korte stappen. Je kunt later alles aanpassen via Instellingen → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Wat wordt er opgeslagen?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = aanbevolen voor de meeste spelers.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Aanbevolen</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Uiterlijk</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Vorige sessie laden bij opstarten</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Filters toepassen op berichten uit vorige sessies</value>
</data>
@@ -313,14 +304,11 @@
<value>(ongewijzigd)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Probeer het uit: typ /tell &lt;Spelernaam&gt; in de chat. Hellion Chat opent een eigen tabblad voor het gesprek en laadt de laatste {0} berichten vooraf.</value>
<value>Probeer het uit: typ /tell &lt;Spelernaam&gt; in de chat. Hellion Chat opent een eigen tabblad voor het gesprek en laadt de laatste {0} berichten vooraf.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Instellingen → Hellion Chat om later te verfijnen</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Exporteren (AVG Art. 15 — Recht op inzage)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Exporteer opgeslagen berichten als Markdown, JSON of CSV. Hiermee kun je een inzageverzoek van een persoon wiens berichten je hebt opgeslagen afhandelen, of je eigen geschiedenis meenemen.</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 community-vertalers (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Actieve tells</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Tabblad losmaken</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Omzetten naar permanent tabblad</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Zet deze TempTell om naar een gewoon tabblad. De tell-koppeling met de gesprekspartner wordt verbroken: het tabblad vangt berichten voortaan op via de kanaalsfilters. Gebruik "Tabblad vastpinnen" als je wilt dat het tabblad een relog overleeft terwijl het gekoppeld blijft aan deze gesprekspartner.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Vastgepinde tabbladen overleven een relog en blijven gekoppeld aan deze gesprekspartner.</value>
</data>
@@ -504,7 +486,7 @@
<value>Vastgepind: overleeft relog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Let op: Als XIV Messenger of een vergelijkbare plugin tells onderdrukt, schakel dan de optie "Suppress DMs" daar uit zodat Hellion Chat tells kan ontvangen en de auto-tabbladen kan openen.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Tell-geschiedenis in auto-tabbladen</value>
</data>
@@ -559,15 +541,9 @@
<value>Werkt alleen als auto-tell-tabbladen zijn ingeschakeld in het Chat-tabblad.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Instellingen geherstructureerd</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 heeft de instellingen geherstructureerd in thematische tabbladen. Je chatdatabase en berichtengeschiedenis blijven ongewijzigd. Instellingen zijn teruggezet naar de standaardwaarden. Als je je privacyprofiel opnieuw wilt kiezen, staat de knop Wizard opnieuw tonen in het tabblad Privacy. Een back-up van de vorige configuratie staat bij HellionChat.json.pre-v10-backup naast het actieve configuratiebestand.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Algemeen</value>
</data>
@@ -590,9 +566,9 @@
<value>Over</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Tijdstempels</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Vensterkader</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Symboolkiezer naast de chatinvoer tonen</value>
</data>
@@ -621,23 +597,17 @@
<value>Voegt een kleine knop links van de kanaalkiezer toe die een popup opent met FFXIV-pictogrammen en een samengestelde symbolenlijst. Schakel uit als je een slankere invoerbalk verkiest.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Opslag</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Overzicht</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Onderhoud</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Systeem</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Als je meerdere linkshells gebruikt, raadt de maintainer aan om één tabblad per shell te gebruiken voor een overzichtelijker geheel. Dupliceer het tabblad en beperk de kanaalselectie in elke kopie.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Tabblad-pictogram</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Verplaatst het chatvenster en alle actieve pop-outs terug naar de linkerbovenhoek van de primaire monitor. Handig wanneer een venster buiten het zichtbare gebied is beland na een wijziging in de schermindeling (monitor losgekoppeld, resolutie gewijzigd). De plugin voert ook eenmalig per sessie een automatische grenscontrole uit; deze knop is de handmatige nooduitgang als er toch iets onbereikbaar blijft.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Nieuw in v0.6.0: je kunt nu direct typen in pop-outs. Schakel de hoofdschakelaar in via de vensterinstellingen.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Begrepen</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Vensterinstellingen openen</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Je kunt elk chattabblad als een eigen venster openen. Klik op het venster-pictogram rechtsboven of klik met rechts op het tabblad. Nieuw in v0.6.1: pop-outinvoer is standaard actief (uit te schakelen via Instellingen → Venster).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Begrepen</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Instellingen openen</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat kan niet starten terwijl Chat 2 geladen is.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Schakel Chat 2 uit in /xlplugins en schakel daarna Hellion Chat opnieuw in.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Algemeen</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Taal, invoer, audio en prestaties.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Uiterlijk</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Vensterdekking, lettertypen, beweging</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Een theme kiezen of je eigen theme importeren</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Venster</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Wanneer het venster zichtbaar is en of het verplaatst kan worden.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, voorbeeld, berichtgedrag en emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Tabbladen</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Aangepaste chattabbladen aanmaken en configureren.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Database</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Opslag, migratie, verouderde opschoning</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Over</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Extensies, versie, projectinformatie, vertalers en changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Bewaren</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Privacy voorop</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Open</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Gegevens en privacy</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Privacyfilter, retentie, opschoning, export en databasestatistieken.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Geavanceerd (Shift+klik om te openen)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 heeft het instellingenmenu opnieuw ingedeeld en de oude optie "Stijl overschrijven" verwijderd (vervangen door het themasysteem uit 1.1.0). Je overige instellingen zijn ongewijzigd. Venstertransparantie is verplaatst naar "Theme &amp; Layout". Een back-up van de vorige configuratie staat bij pluginConfigs/HellionChat.json.pre-v16-backup naast de actieve HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Plugin-integraties laten HellionChat samenwerken met andere geïnstalleerde Dalamud-plugins. Elke integratie detecteert automatisch zijn doelplugin en schakelt zichzelf stil uit als die ontbreekt.</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Invoer</value>
</data>
@@ -999,9 +897,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Automatische tell-tabbladen</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Links en tooltips</value>
</data>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Dit bericht bevat plugin-exclusieve symbolen die andere spelers mogelijk als lege vakjes zien. Druk opnieuw op Enter om toch te verzenden.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Symbool invoegen</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Instellingen</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Chat verbergen (Enter haalt hem terug)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Dit tabblad terugzetten in het hoofdvenster</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Er wordt al een andere databasebewerking uitgevoerd: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>bewaartermijnopschoning</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>export</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>opschoning</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>wissen van de geschiedenis</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Het privacyfilter staat uit, dus elk kanaal wordt opgeslagen en niets in de database spreekt je instellingen tegen. Zet het filter eerst aan en kies kanalen.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Er is geen kanaal geselecteerd, dus een opschoning zou de hele geschiedenis wissen. Kies de kanalen die je wilt bewaren, of gebruik de wisknop als je echt alles kwijt wilt.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Er zijn {0:N0} berichten opgeslagen. Wil je een kopie houden, exporteer ze dan voordat je wist.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: voert de opschoning nu meteen uit in plaats van te wachten op de dagelijkse ronde. Wist berichten ouder dan de limieten hierboven.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Het wissen van de geschiedenis is mislukt. Er is niets verwijderd, zie /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetrie</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Er wordt geen telemetrie verzameld. De plug-in stuurt niets over jou of je gebruik ergens heen.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Automatische vertaling</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Ga naar het nieuwste bericht</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Kaartmarkering invoegen &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Gekoppeld voorwerp invoegen &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>uit</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Gedrag</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Sneltoetsen</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Meldingen</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Weergavemodi</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Geschiedenis</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Commandohulp</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Plug-invermelding</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Lay-outmodus</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Dekking</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Formaatgedrag</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Tells automatisch openen</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Zijbalk</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Merk</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Links</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integraties</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Met dank aan</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licentie</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Klik op een knop en druk daarna de toetsencombinatie. Esc wist.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Naar het volgende tabblad</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Naar het vorige tabblad</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Wisselen bouwt de lettertype-atlas opnieuw op, dus de chat is even leeg.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24-uursklok</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Geschiedenis van eerdere sessies tonen</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Uit betekent dat het logboek bij elke start leeg begint en zich alleen vult met daarna ontvangen berichten.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Zijde van de commandohulp</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Aan welke kant de lijst met commandotips verschijnt tijdens het typen.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Modus voor automatisch openen van tells</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Waar een tell opent wanneer die binnenkomt.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Bij elke tell naar het tabblad schakelen</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Anders opent het tabblad na de eerste op de achtergrond.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Zijbalk</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Tabbladen bovenaan</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Tabbladpositie</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Waar de tabbladlijst in het hoofdvenster staat.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Titelbalk tonen</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Titelbalk voor pop-outvensters</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Verplaatsen toestaan</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Formaat wijzigen toestaan</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Omschakeldrempel zijbalk</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Onder deze breedte vouwt de zijbalk samen tot tabbladen bovenaan, in pixels.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Positie van het voorbeeld</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Voorbeeld alleen tijdens typen tonen</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea-repository</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifest van eigen repository</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Actief thema: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Aftakken en bewerken</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Ingebouwde thema's kun je niet rechtstreeks bewerken. Aftakken maakt een eigen kopie die je kunt bewerken en opslaan.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Thema bewerken</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Bezig met bewerken: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Vlakken</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Randen</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Tekst</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identiteit</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Status</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Opslaan</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Annuleren</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Terugzetten naar bron</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Terugzetten kan niet tijdens het bewerken van een aftakking. Sla eerst op of annuleer.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Sla je wijzigingen eerst op of verwerp ze</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Eigen ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Actief thema aftakken</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Themabestand importeren…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Pad naar JSON-bestand (of sleep het naar de map)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Thema exporteren</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Koel</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Natuurlijk</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Klassiek</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (meegeleverd)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Speltypografie</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Globaal: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Actief: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Typ een bericht...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Dupliceren</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>voorbeeld</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>onderhoud</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} tabblad</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} tabbladen</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} tell</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} tells</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} ber.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k ber.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Kampioen» Voorbeeld</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>open</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Niet ingelogd</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Meer acties</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Zabezpieczenie na wypadek ChatTypes dodanych przez przyszłe patche FFXIV, których plugin jeszcze nie zna. Domyślnie WYŁĄCZONE (minimalizacja danych). Włącz, jeśli chcesz, żeby przyszłe kanały też były w pełni logowane.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Zastosuj filtr do istniejącej bazy danych</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Filtr prywatności działa tylko na nowe wiadomości. Czyszczenie poniżej pozwala retroaktywnie usunąć już zapisane wiadomości, które nie pasują do zapisanej listy dozwolonych.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Czyszczenie używa ZAPISANEJ listy dozwolonych (Plugin.Config), a nie niezapisanych zmian powyżej. Najpierw kliknij Zapisz, jeśli chcesz zastosować bieżące zmiany.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Ręczne uruchomienie używa ZAPISANEJ polityki przechowywania, nie wartości suwaków powyżej. Najpierw kliknij Zapisz, jeśli chcesz zastosować bieżące zmiany.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Podgląd jest nieaktualny: lista dozwolonych zmieniła się od ostatniego odświeżenia. Kliknij Odśwież, aby przeliczyć.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Zastosuj przechowywanie teraz</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Natychmiast uruchamia czyszczenie przechowywania przy użyciu ZAPISANEJ polityki. Najpierw zapisz zmiany.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Czyszczenie przechowywania trwa w tle…</value>
</data>
@@ -184,7 +172,7 @@
<value>Wybierz profil startowy. Wszystko możesz zmienić później w Ustawieniach → Prywatność.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Minimalizacja danych (zalecane)</value>
<value>Minimalizacja danych</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Przechowywane są tylko twoje własne rozmowy: tells, grupa, FC, linkshells, cross-world linkshells, sojusz i ExtraChat. Czat publiczny, dialogi NPC i spam systemowy są odrzucane na poziomie zapisu. Czas przechowywania według domyślnych wartości specyfikacji (tells 365 dni, własne kanały rozmów 90 dni).</value>
@@ -226,7 +214,13 @@
<value>Witaj w Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Fork Chat 2 od Hellion Forge z domyślnymi ustawieniami chroniącymi prywatność, spójną identyfikacją wizualną i drobnymi usprawnieniami komfortu gry.</value>
<value>Twoje okno czatu od Hellion Forge. Prywatność od pierwszego uruchomienia, 25 języków, a układ ustawiasz sam.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat powstał jako fork Chat 2. Od tamtej pory oba projekty rozeszły się na tyle, że ich bazy kodu nie są już zgodne.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Pluginy to w Final Fantasy XIV szara strefa: warunki korzystania Square Enix ich nie obejmują, a Naoki Yoshida publicznie prosił, by ich nie reklamować. Nie poruszaj więc tego tematu na Say, Yell, Shout ani na żadnym innym kanale publicznym.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Trzy krótkie kroki. Wszystko możesz zmienić później w Ustawieniach → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Co ma być zapisywane?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = zalecane dla większości graczy.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Zalecane</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Wygląd</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Wczytaj poprzednią sesję przy uruchomieniu</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Stosuj filtry do wiadomości z poprzednich sesji</value>
</data>
@@ -313,14 +304,11 @@
<value>(bez zmian)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Wypróbuj: wpisz /tell &lt;Nazwa gracza&gt; w czacie. Hellion Chat otworzy dedykowaną zakładkę dla rozmowy i wstępnie wczyta ostatnie {0} wiadomości.</value>
<value>Wypróbuj: wpisz /tell &lt;Nazwa gracza&gt; w czacie. Hellion Chat otworzy dedykowaną zakładkę dla rozmowy i wstępnie wczyta ostatnie {0} wiadomości.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Ustawienia → Hellion Chat, aby dostosować później</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Eksport (GDPR Art. 15 — Prawo dostępu)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Eksportuj zapisane wiadomości jako Markdown, JSON lub CSV. Pozwala to zrealizować wniosek o dostęp od osoby, której wiadomości przechowujesz, lub zabrać własną historię ze sobą.</value>
</data>
@@ -457,7 +445,7 @@
<value>Tłumacze społeczności Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Aktywne tells</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Odepnij zakładkę</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Przekształć w stałą zakładkę</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Zamienia ten TempTell w zwykłą zakładkę. Powiązanie tell z partnerem zostaje usunięte: od tej pory zakładka będzie przechwytywać wiadomości na podstawie filtrów kanałów. Jeśli chcesz, żeby „zakładka przeżyła relog i pozostała powiązana z tym partnerem", użyj zamiast tego Przypnij zakładkę.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Przypięte zakładki przeżywają relog i pozostają powiązane z tym partnerem rozmowy.</value>
</data>
@@ -504,7 +486,7 @@
<value>Przypięta: przeżywa relog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Uwaga: Jeśli XIV Messenger lub podobny plugin blokuje tells, wyłącz tam opcję „Suppress DMs", aby Hellion Chat mógł odbierać tells i otwierać auto-zakładki.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Historia tell w auto-zakładkach</value>
</data>
@@ -559,15 +541,9 @@
<value>Działa tylko wtedy, gdy auto-zakładki tell są włączone w zakładce Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Ustawienia przeorganizowane</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 przeorganizował ustawienia w tematyczne zakładki. Twoja baza danych czatu i historia wiadomości pozostają bez zmian. Ustawienia zostały zresetowane do domyślnych. Jeśli chcesz ponownie wybrać profil prywatności, przycisk Otwórz ponownie znajduje się w zakładce Prywatność. Kopia zapasowa poprzedniej konfiguracji znajduje się w pliku HellionChat.json.pre-v10-backup obok aktywnego pliku konfiguracji.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Ogólne</value>
</data>
@@ -590,9 +566,9 @@
<value>O pluginie</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Znaczniki czasu</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Ramka okna</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Pokaż przycisk wyboru symboli obok pola wprowadzania czatu</value>
</data>
@@ -621,23 +597,17 @@
<value>Dodaje mały przycisk po lewej stronie wskaźnika kanału, który otwiera popup z ikonami FFXIV i listą wybranych symboli. Wyłącz, jeśli wolisz bardziej minimalistyczny pasek wprowadzania.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Przechowywanie</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Przegląd</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Konserwacja</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>System</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emoty</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Jeśli używasz wielu linkshells, maintainer zaleca po jednej zakładce na każdą dla lepszego przeglądu. Zduplikuj zakładkę i ogranicz wybór kanałów w każdej kopii.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Ikona zakładki</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Przenosi okno czatu i wszystkie aktywne pop-outy z powrotem do lewego górnego rogu głównego monitora. Przydatne, gdy okno znalazło się poza widocznym obszarem po zmianie układu wyświetlania (odłączony monitor, zmieniona rozdzielczość). Plugin wykonuje też automatyczne sprawdzenie granic raz na sesję; ten przycisk to ręczna opcja awaryjna, gdy coś nadal pozostaje niedostępne.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Nowość w v0.6.0: Możesz teraz pisać bezpośrednio w pop-outach. Włącz główny przełącznik w ustawieniach okna.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Rozumiem</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Otwórz ustawienia okna</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Możesz otworzyć dowolną zakładkę czatu jako własne okno. Kliknij ikonę okna w prawym górnym rogu lub kliknij prawym przyciskiem zakładkę. Nowość w v0.6.1: wprowadzanie w pop-oucie jest domyślnie aktywne (można wyłączyć w Ustawieniach → Okno).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Rozumiem</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Otwórz ustawienia</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat nie może uruchomić się, gdy Chat 2 jest załadowany.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Wyłącz Chat 2 w /xlplugins, a następnie ponownie włącz Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Ogólne</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Język, wprowadzanie, audio i wydajność.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Wygląd</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Przezroczystość okna, czcionki, animacje</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Motywy</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Wybierz motyw lub zaimportuj własny</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Okno</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Kiedy okno jest widoczne i czy można je przesuwać.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, podgląd, zachowanie wiadomości i emoty.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Zakładki</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Twórz i konfiguruj niestandardowe zakładki czatu.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Baza danych</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Przechowywanie, migracja, stare czyszczenie</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>O wtyczce</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Rozszerzenia, wersja, informacje o projekcie, tłumacze i changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Motywy</value>
</data>
@@ -803,7 +707,7 @@
<value>Zachowaj</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Prywatność przede wszystkim</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Otwarty</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Dane i prywatność</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Filtr prywatności, przechowywanie, czyszczenie, eksport i statystyki bazy danych.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Zaawansowane (Shift+kliknięcie, aby otworzyć)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 przeorganizował menu ustawień i usunął starą opcję „Override style" (zastąpioną przez system motywów z wersji 1.1.0). Pozostałe ustawienia pozostają bez zmian. Przezroczystość okna została przeniesiona do „Theme &amp; Layout". Kopia zapasowa poprzedniej konfiguracji znajduje się w pluginConfigs/HellionChat.json.pre-v16-backup obok aktywnego HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Integracje z pluginami pozwalają HellionChat współpracować z innymi zainstalowanymi pluginami Dalamud. Każda integracja automatycznie wykrywa swój cel i cicho się wyłącza, gdy docelowy plugin jest niedostępny.</value>
</data>
@@ -955,7 +853,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Wejście</value>
</data>
@@ -998,9 +896,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Automatyczne karty tell</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotki</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Linki i podpowiedzi</value>
</data>
@@ -1145,4 +1040,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Ta wiadomość zawiera symbole tylko dla wtyczki, które inni gracze mogą widzieć jako puste kwadraty. Naciśnij Enter ponownie, aby wysłać mimo to.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Wstaw symbol</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Ustawienia</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Ukryj czat (Enter go przywraca)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Przywróć tę kartę do okna głównego</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Trwa już inna operacja na bazie danych: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>porządkowanie według czasu przechowywania</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>eksport</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>porządkowanie</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>usuwanie historii</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Filtr prywatności jest wyłączony, więc zapisywany jest każdy kanał i nic w bazie danych nie kłóci się z twoimi ustawieniami. Najpierw włącz filtr i wybierz kanały.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Nie wybrano żadnego kanału, więc porządkowanie usunęłoby całą historię. Wybierz kanały, które chcesz zachować, albo użyj przycisku czyszczenia, jeśli naprawdę chcesz usunąć wszystko.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Zapisanych jest {0:N0} wiadomości. Jeśli chcesz zachować kopię, wyeksportuj je przed wyczyszczeniem.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: uruchamia porządkowanie od razu, zamiast czekać na codzienny przebieg. Usuwa wiadomości starsze niż limity powyżej.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Usuwanie historii nie powiodło się. Nic nie zostało usunięte, zobacz /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetria</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Nie zbieramy żadnej telemetrii. Plugin nigdzie nie wysyła informacji o tobie ani o twoim użytkowaniu.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Autotłumaczenie</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Przejdź do najnowszej wiadomości</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Wstaw znacznik mapy &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Wstaw powiązany przedmiot &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>wyłączone</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Zachowanie</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Skróty klawiszowe</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Powiadomienia</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Tryby wyświetlania</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Historia</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Pomoc do poleceń</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Informacja o pluginie</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Tryb układu</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Nieprzezroczystość</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Zmiana rozmiaru</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Automatyczne otwieranie tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Panel boczny</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Marka</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Odnośniki</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integracje</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Twórcy</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licencja</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Kliknij przycisk, a następnie naciśnij kombinację klawiszy. Esc czyści.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Przejdź do następnej zakładki</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Przejdź do poprzedniej zakładki</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Zmiana przebudowuje atlas czcionek, więc czat na chwilę pustoszeje.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>Zegar 24-godzinny</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Pokaż historię z poprzednich sesji</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Wyłączone oznacza, że dziennik startuje pusty przy każdym uruchomieniu gry i wypełnia się tylko wiadomościami odebranymi od tego momentu.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Strona pomocy do poleceń</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Po której stronie pojawia się lista podpowiedzi podczas pisania.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Tryb automatycznego otwierania tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Gdzie otwiera się tell, gdy nadejdzie.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Przełączaj na zakładkę przy każdym tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>W przeciwnym razie zakładka po pierwszym otwiera się w tle.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Panel boczny</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Zakładki u góry</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Rozmieszczenie zakładek</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Gdzie w oknie głównym znajduje się lista zakładek.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Pokaż pasek tytułu</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Pokaż pasek tytułu w oknach odłączonych</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Zezwól na przesuwanie</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Zezwól na zmianę rozmiaru</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Próg automatycznego przełączania panelu bocznego</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Poniżej tej szerokości panel boczny zwija się w zakładki u góry, w pikselach.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Pozycja podglądu</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Pokaż podgląd tylko podczas pisania</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Repozytorium Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifest własnego repozytorium</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Aktywny motyw: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Rozgałęź i edytuj</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Wbudowanych motywów nie można edytować bezpośrednio. Rozgałęzienie tworzy własną kopię, którą możesz edytować i zapisać.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Edytuj motyw</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Edytowanie: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Powierzchnie</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Obramowania</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Tekst</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Tożsamość</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Status</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Zapisz</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Anuluj</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Przywróć do źródła</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Przywracanie jest niedostępne podczas edycji rozgałęzienia. Najpierw zapisz lub anuluj.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Najpierw zapisz lub odrzuć swoje zmiany</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Własne ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Rozgałęź aktywny motyw</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importuj plik motywu…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Ścieżka do pliku JSON (lub przeciągnij do folderu)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Eksportuj motyw</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Chłodne</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturalne</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Klasyczne</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (w zestawie)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Czcionka z gry</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Globalna: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Aktywna: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Napisz wiadomość...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplikuj</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>podgląd</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>konserwacja</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} zakładka</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} zakładki</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} szept</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} szepty</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} wiad.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k wiad.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Mistrz» Podgląd</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>otwarte</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Niezalogowany</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Więcej działań</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Rede de segurança para ChatTypes adicionados por patches futuros do FFXIV que o plugin ainda não conhece. O padrão é DESATIVADO (minimização de dados). Ative se quiser que canais futuros também sejam registrados por completo.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Aplicar filtro ao banco de dados existente</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>O filtro de privacidade afeta apenas novas mensagens. A limpeza abaixo permite remover retroativamente mensagens já armazenadas que não correspondem à sua lista de permissões salva.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>A limpeza usa sua lista de permissões SALVA (Plugin.Config), não as alterações não salvas acima. Clique em Salvar primeiro se quiser que suas alterações atuais sejam aplicadas.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>A execução manual usa sua política de retenção SALVA, não os valores dos controles acima. Clique em Salvar primeiro se quiser que a execução aplique suas alterações atuais.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>A prévia está desatualizada: sua lista de permissões mudou desde a última atualização. Clique em Atualizar para recalcular.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Aplicar retenção agora</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Executa a limpeza de retenção imediatamente usando a política SALVA. Salve suas alterações primeiro.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Limpeza de retenção em execução em segundo plano…</value>
</data>
@@ -184,7 +172,7 @@
<value>Escolha um perfil inicial. Você pode ajustar tudo depois em Configurações → Privacidade.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Minimização de dados (recomendado)</value>
<value>Minimização de dados</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Apenas suas próprias conversas são armazenadas: tells, grupo, FC, linkshells, cross-world linkshells, aliança e ExtraChat. Bate-papo público, diálogos de NPC e spam de sistema são descartados no nível de armazenamento. A retenção segue os padrões da spec (tells 365 dias, canais de conversa próprios 90 dias).</value>
@@ -226,7 +214,13 @@
<value>Bem-vindo ao Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Um fork do Chat 2 pela Hellion Forge com padrões voltados para privacidade, visual consistente com a marca e alguns toques de qualidade de vida.</value>
<value>Sua janela de chat, da Hellion Forge. Privacidade desde o primeiro uso, 25 idiomas, e você organiza do seu jeito.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>O Hellion Chat começou como um fork do Chat 2. Desde então os dois se afastaram a ponto de as bases de código não serem mais compatíveis.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Plugins são uma zona cinzenta no Final Fantasy XIV: os termos de uso da Square Enix não os cobrem, e Naoki Yoshida pediu publicamente que não sejam divulgados. Mantenha o assunto fora de Falar, Grita, Berrar e de qualquer outro canal público.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Três passos rápidos. Você pode mudar tudo depois em Configurações → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>O que será armazenado?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = recomendado para a maioria dos jogadores.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Recomendado</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Visual</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Carregar sessão anterior ao iniciar</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Aplicar filtros às mensagens de sessões anteriores</value>
</data>
@@ -313,14 +304,11 @@
<value>(sem alteração)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Experimente: digite /tell &lt;Nome do Jogador&gt; no chat. O Hellion Chat abre uma aba dedicada para a conversa e pré-carrega as últimas {0} mensagens.</value>
<value>Experimente: digite /tell &lt;Nome do Jogador&gt; no chat. O Hellion Chat abre uma aba dedicada para a conversa e pré-carrega as últimas {0} mensagens.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Configurações → Hellion Chat para ajustar depois</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Exportar (GDPR Art. 15 — Direito de acesso)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Exporte mensagens armazenadas como Markdown, JSON ou CSV. Isso permite atender a uma solicitação de acesso de uma pessoa cujas mensagens você armazenou, ou levar seu próprio histórico com você.</value>
</data>
@@ -457,7 +445,7 @@
<value>Tradutores da comunidade do Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Tells ativos</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Desafixar aba</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Promover para permanente</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Transforma este TempTell em uma aba regular. O vínculo de tell com o parceiro é removido: a aba passará a capturar mensagens pelos filtros de canal a partir de agora. Para "aba sobrevive ao relog mantendo o vínculo com este parceiro", use Fixar aba.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Abas fixadas sobrevivem ao relog e permanecem vinculadas a este parceiro de conversa.</value>
</data>
@@ -504,7 +486,7 @@
<value>Fixado: sobrevive ao relog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Atenção: se o XIV Messenger ou um plugin similar suprimir tells, desative a opção "Suppress DMs" nele para que o Hellion Chat possa receber tells e abrir as abas automáticas.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Histórico de tell nas abas automáticas</value>
</data>
@@ -559,15 +541,9 @@
<value>Só tem efeito quando as abas de tell automáticas estão ativadas na aba Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Configurações reestruturadas</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>O Hellion Chat 0.5.0 reestruturou as configurações em abas temáticas. Seu banco de dados de chat e histórico de mensagens permanecem inalterados. As configurações foram redefinidas para os padrões. Se quiser selecionar seu perfil de privacidade novamente, o botão Reabrir está na aba Privacidade. Um backup da configuração anterior está em HellionChat.json.pre-v10-backup ao lado do arquivo de configuração ativo.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Geral</value>
</data>
@@ -590,9 +566,9 @@
<value>Sobre</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Timestamps</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Moldura da janela</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Mostrar botão de seleção de símbolos ao lado da entrada de chat</value>
</data>
@@ -621,23 +597,17 @@
<value>Adiciona um pequeno botão à esquerda do indicador de canal que abre um popup com ícones do FFXIV e uma lista de símbolos selecionados. Desative se preferir uma barra de entrada mais simples.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Armazenamento</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Visão geral</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Manutenção</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Sistema</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Se você usa várias linkshells, o mantenedor recomenda uma aba por shell para uma visão mais organizada. Duplique a aba e restrinja a seleção de canais em cada cópia.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Ícone da aba</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Move a janela de chat e todos os pop-outs ativos de volta para o canto superior esquerdo do monitor principal. Útil quando uma janela foi parar fora da área visível após uma mudança de layout de tela (monitor desconectado, resolução alterada). O plugin também realiza uma verificação automática de limites uma vez por sessão; este botão é a saída manual caso algo ainda fique inacessível.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Novidade na v0.6.0: agora você pode digitar diretamente nos pop-outs. Ative a chave mestra nas configurações de Janela.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Entendi</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Abrir configurações de janela</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Você pode abrir qualquer aba de chat como sua própria janela. Clique no ícone de janela no canto superior direito ou clique com o botão direito na aba. Novidade na v0.6.1: a entrada em pop-out está ativa por padrão (pode ser desativada em Configurações → Janela).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Entendi</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Abrir configurações</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>O Hellion Chat não pode iniciar enquanto o Chat 2 estiver carregado.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Desative o Chat 2 em /xlplugins e depois reative o Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Geral</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Idioma, entrada, áudio e performance.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Aparência</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Opacidade da janela, fontes, animação</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Escolha um tema ou importe o seu</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Janela</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Quando a janela é visível e se ela pode ser movida.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, prévia, comportamento de mensagens e emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Abas</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Crie e configure abas de chat personalizadas.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Banco de Dados</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Armazenamento, migração, limpeza legada</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Sobre</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Extensões, versão, informações do projeto, tradutores e changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Manter</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Privacidade primeiro</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Aberto</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Dados e privacidade</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Filtro de privacidade, retenção, limpeza, exportação e estatísticas do banco de dados.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Avançado (Shift+clique para abrir)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>O Hellion Chat 1.2.1 reorganizou o menu de configurações e removeu a antiga opção "Substituir estilo" (substituída pelo sistema de temas da versão 1.1.0). Suas demais configurações permanecem inalteradas. A transparência da janela foi migrada para "Theme &amp; Layout". Um backup da configuração anterior está em pluginConfigs/HellionChat.json.pre-v16-backup ao lado do HellionChat.json ativo.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>As integrações de plugin permitem que o HellionChat trabalhe junto com outros plugins Dalamud instalados. Cada integração detecta automaticamente seu alvo e se desativa silenciosamente quando o plugin alvo está ausente.</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Entrada</value>
</data>
@@ -999,9 +897,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Abas de tell automático</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Links e dicas</value>
</data>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Esta mensagem contém símbolos exclusivos do plugin que outros jogadores podem ver como caixas vazias. Pressione Enter novamente para enviar mesmo assim.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Inserir símbolo</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Configurações</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Ocultar o chat (Enter para trazer de volta)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Devolver esta aba à janela principal</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Outra operação de banco de dados está em andamento: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>limpeza de retenção</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>exportação</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>limpeza</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>exclusão do histórico</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>O filtro de privacidade está desligado, então todos os canais são salvos e nada no banco de dados contradiz suas configurações. Ligue o filtro e escolha os canais primeiro.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Nenhum canal está selecionado, então uma limpeza apagaria todo o histórico. Escolha os canais que quer manter, ou use o botão de apagar se realmente quiser remover tudo.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Há {0:N0} mensagens salvas. Se quiser manter uma cópia, exporte-as antes de apagar.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: executa a limpeza de retenção agora em vez de esperar a varredura diária. Apaga mensagens mais antigas que os limites acima.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Falha ao apagar o histórico. Nada foi removido, veja /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetria</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Nenhuma telemetria é coletada. O plugin não envia nada sobre você ou seu uso para lugar nenhum.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Tradução automática</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Ir para a mensagem mais recente</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Inserir marcação do mapa &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Inserir item vinculado &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>desativado</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Comportamento</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Atalhos de teclado</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Notificações</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Modos de exibição</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Histórico</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Ajuda de comandos</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Aviso de plugin</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Modo de layout</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Opacidade</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Comportamento de redimensionamento</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Abertura automática de tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Barra lateral</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Marca</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Links</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrações</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Créditos</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licença</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Clique em um botão e depois pressione a combinação de teclas. Esc limpa.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Ir para a próxima aba</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Ir para a aba anterior</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Trocar reconstrói o atlas de fontes, então o chat fica vazio por um instante.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>Relógio de 24 horas</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Mostrar histórico de sessões anteriores</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Desligado, o registro começa vazio a cada início do jogo e só se enche com as mensagens recebidas a partir daí.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Lado da ajuda de comandos</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>De que lado a lista de sugestões aparece enquanto você digita.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Modo de abertura automática de tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Onde um tell abre quando chega.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Mudar para a aba a cada tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Caso contrário, a aba abre em segundo plano após o primeiro.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Barra lateral</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Abas no topo</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Posição das abas</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Onde a lista de abas fica na janela principal.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Mostrar barra de título</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Mostrar barra de título nas janelas destacadas</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Permitir mover</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Permitir redimensionar</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Limite de troca automática da barra lateral</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Abaixo desta largura a barra lateral vira abas no topo, em pixels.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Posição da pré-visualização</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Mostrar a pré-visualização apenas ao digitar</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Repositório Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifesto do repositório personalizado</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Tema ativo: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Bifurcar e editar</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Temas integrados não podem ser editados diretamente. Bifurcar cria uma cópia personalizada que você pode editar e salvar.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Editar tema</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Editando: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Superfícies</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Bordas</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Texto</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identidade</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Status</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Salvar</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Cancelar</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Restaurar para o original</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Não é possível restaurar enquanto edita uma bifurcação. Salve ou cancele primeiro.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Salve ou descarte suas alterações primeiro</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Personalizados ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Bifurcar o tema ativo</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importar arquivo de tema…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Caminho do arquivo JSON (ou arraste para a pasta)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Exportar tema</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Frios</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturais</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Clássicos</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retrô</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (incluída)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Fonte do jogo</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Global: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Ativa: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Digite uma mensagem...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplicar</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>pré-visualização</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>manutenção</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} aba</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} abas</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} sussurro</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} sussurros</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} msg</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k msg</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Campeão» Pré-visualização</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>aberto</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Não conectado</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Mais ações</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Rede de segurança para ChatTypes adicionados por futuras atualizações de FFXIV que o plugin ainda não reconhece. A predefinição é DESATIVADO (minimização de dados). Ativa se quiseres que futuros canais sejam também registados na íntegra.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Aplicar filtro à base de dados existente</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>O filtro de privacidade só afeta novas mensagens. A limpeza abaixo permite remover retroativamente mensagens já armazenadas que não correspondem à tua lista de permissões guardada.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>A limpeza usa a tua lista de permissões GUARDADA (Plugin.Config), não as alterações por guardar acima. Clica em Guardar primeiro se quiseres que as tuas alterações atuais sejam aplicadas.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>A execução manual usa a tua política de retenção GUARDADA, não os valores do cursor acima. Clica em Guardar primeiro se quiseres que a execução aplique as tuas alterações atuais.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>A pré-visualização está desatualizada: a tua lista de permissões mudou desde a última atualização. Clica em Atualizar para recalcular.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Aplicar retenção agora</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Executa a limpeza de retenção imediatamente com a política GUARDADA. Guarda as tuas alterações primeiro.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Limpeza de retenção a decorrer em segundo plano…</value>
</data>
@@ -184,7 +172,7 @@
<value>Escolhe um perfil inicial. Podes ajustar tudo depois em Definições → Privacidade.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Minimização de dados (recomendado)</value>
<value>Minimização de dados</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Só as tuas próprias conversas são armazenadas: tells, grupo, FC, linkshells, cross-world linkshells, aliança e ExtraChat. O chat público, os diálogos de NPC e o spam de sistema são descartados ao nível do armazenamento. A retenção segue os valores predefinidos da spec (tells 365 dias, canais de conversas próprias 90 dias).</value>
@@ -226,7 +214,13 @@
<value>Bem-vindo ao Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Um fork do Chat 2 da Hellion Forge com predefinições com privacidade em mente, visuais consistentes com a marca e alguns retoques de qualidade de vida.</value>
<value>A tua janela de conversa, da Hellion Forge. Privacidade desde o primeiro arranque, 25 idiomas, e organizas tudo como quiseres.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>O Hellion Chat começou como um fork do Chat 2. Desde então os dois afastaram-se ao ponto de as bases de código já não serem compatíveis.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Os plugins são uma zona cinzenta no Final Fantasy XIV: os termos de utilização da Square Enix não os abrangem e Naoki Yoshida pediu publicamente que não fossem promovidos. Mantém, portanto, o assunto fora de Say, Yell, Shout e de qualquer outro canal público.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Três passos rápidos. Podes mudar tudo depois em Definições → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>O que fica armazenado?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = recomendado para a maioria dos jogadores.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Recomendado</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Visual</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Carregar sessão anterior no arranque</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Aplicar filtros a mensagens de sessões anteriores</value>
</data>
@@ -313,14 +304,11 @@
<value>(sem alterações)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Experimenta: escreve /tell &lt;Nome do Jogador&gt; no chat. O Hellion Chat abre um separador dedicado para a conversa e pré-carrega as últimas {0} mensagens.</value>
<value>Experimenta: escreve /tell &lt;Nome do Jogador&gt; no chat. O Hellion Chat abre um separador dedicado para a conversa e pré-carrega as últimas {0} mensagens.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Definições → Hellion Chat para ajustar mais tarde</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Exportar (GDPR Art. 15 — Direito de acesso)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Exporta mensagens armazenadas em Markdown, JSON ou CSV. Permite responder a um pedido de acesso de uma pessoa cujas mensagens guardaste, ou levar o teu próprio histórico contigo.</value>
</data>
@@ -457,7 +445,7 @@
<value>Tradutores da comunidade do Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Tells ativos</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Desafixar separador</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Promover a permanente</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Transforma este TempTell num separador normal. A ligação de tell ao parceiro é removida: o separador passará a capturar mensagens pelos seus filtros de canal. Para "separador sobrevive ao relog mantendo a ligação a este parceiro", usa Fixar separador.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Os separadores fixos sobrevivem ao relog e mantêm a ligação a este parceiro de conversa.</value>
</data>
@@ -504,7 +486,7 @@
<value>Fixado: sobrevive ao relog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Nota: Se o XIV Messenger ou um plugin semelhante suprimir tells, desativa a opção "Suppress DMs" lá para que o Hellion Chat possa receber tells e abrir os separadores automáticos.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Histórico de tells em separadores automáticos</value>
</data>
@@ -559,15 +541,9 @@
<value>Só tem efeito quando os separadores de tell automáticos estão ativados no separador Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Definições reestruturadas</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>O Hellion Chat 0.5.0 reestruturou as definições em separadores temáticos. A tua base de dados de chat e o histórico de mensagens permanecem inalterados. As definições foram repostas para os valores predefinidos. Se quiseres voltar a selecionar o teu perfil de privacidade, o botão Reabrir está no separador Privacidade. Uma cópia de segurança da configuração anterior encontra-se em HellionChat.json.pre-v10-backup junto ao ficheiro de configuração ativo.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Geral</value>
</data>
@@ -590,9 +566,9 @@
<value>Sobre</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Marcas de tempo</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Moldura da janela</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Mostrar botão do seletor de símbolos junto à entrada de chat</value>
</data>
@@ -621,23 +597,17 @@
<value>Adiciona um pequeno botão à esquerda do indicador de canal que abre uma janela pop-up com ícones de FFXIV e uma lista curada de símbolos. Desativa se preferires uma barra de entrada mais minimalista.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Armazenamento</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Visão geral</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Manutenção</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Sistema</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Se usares várias linkshells, o maintainer recomenda um separador por shell para uma visão geral mais limpa. Duplica o separador e restringe a seleção de canais em cada cópia.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Ícone do separador</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Move a janela de chat e todas as janelas flutuantes ativas de volta para o canto superior esquerdo do monitor principal. Útil quando uma janela ficou fora da área visível após uma alteração de layout de ecrã (monitor desligado, resolução alterada). O plugin também faz uma verificação automática de limites uma vez por sessão; este botão é a saída manual caso algo continue inacessível.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Novidade na v0.6.0: já podes escrever diretamente em janelas flutuantes. Ativa o interruptor principal nas definições de Janela.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Percebido</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Abrir definições de janela</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Podes abrir qualquer separador de chat como janela própria. Clica no ícone de janela no canto superior direito ou faz clique direito no separador. Novidade na v0.6.1: a entrada em janelas flutuantes está ativa por predefinição (pode ser desativada em Definições → Janela).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Percebido</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Abrir definições</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>O Hellion Chat não pode iniciar enquanto o Chat 2 estiver carregado.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Desativa o Chat 2 em /xlplugins e volta a ativar o Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Geral</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Idioma, entrada, áudio e desempenho.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Aparência</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Opacidade da janela, tipos de letra, movimento</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Escolhe um theme ou importa o teu próprio</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Janela</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Quando a janela está visível e se pode ser movida.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, pré-visualização, comportamento de mensagens e emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Separadores</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Cria e configura separadores de chat personalizados.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Base de dados</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Armazenamento, migração, limpeza de dados antigos</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Sobre</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Extensões, versão, informações do projeto, tradutores e changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Manter</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Privacidade primeiro</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Aberto</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Dados e privacidade</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Filtro de privacidade, retenção, limpeza, exportação e estatísticas da base de dados.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Avançado (Shift+clique para abrir)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>O Hellion Chat 1.2.1 reorganizou o menu de definições e removeu a antiga opção "Substituir estilo" (substituída pelo sistema de themes a partir da versão 1.1.0). As tuas restantes definições ficam inalteradas. A transparência da janela foi migrada para "Theme &amp; Layout". Uma cópia de segurança da configuração anterior encontra-se em pluginConfigs/HellionChat.json.pre-v16-backup junto ao ficheiro HellionChat.json ativo.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>As integrações de plugins permitem que o HellionChat funcione em conjunto com outros plugins Dalamud instalados. Cada integração deteta automaticamente o seu alvo e desativa-se silenciosamente quando o plugin alvo está em falta.</value>
</data>
@@ -955,7 +853,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Entrada</value>
</data>
@@ -998,9 +896,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Separadores de tell automático</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Ligações e dicas</value>
</data>
@@ -1145,4 +1040,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Esta mensagem contém símbolos exclusivos do plugin que outros jogadores podem ver como caixas vazias. Pressiona Enter novamente para enviar mesmo assim.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Inserir símbolo</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Definições</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Ocultar o chat (Enter para o repor)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Devolver este separador à janela principal</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Está em curso outra operação de base de dados: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>limpeza de retenção</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>exportação</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>limpeza</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>eliminação do histórico</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>O filtro de privacidade está desligado, por isso todos os canais são guardados e nada na base de dados contradiz as suas definições. Ligue primeiro o filtro e escolha os canais.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Não está selecionado nenhum canal, por isso uma limpeza apagaria todo o histórico. Escolha os canais que quer manter, ou use o botão de apagar se quiser mesmo remover tudo.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Estão guardadas {0:N0} mensagens. Se quiser manter uma cópia, exporte-as antes de apagar.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: executa a limpeza de retenção agora em vez de esperar a varredura diária. Apaga mensagens mais antigas do que os limites acima.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Falha ao apagar o histórico. Nada foi removido, consulte /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetria</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Não é recolhida qualquer telemetria. O plugin não envia nada sobre si ou sobre a sua utilização.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Tradução automática</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Ir para a mensagem mais recente</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Inserir marcação do mapa &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Inserir item ligado &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>desativado</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Comportamento</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Atalhos de teclado</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Notificações</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Modos de visualização</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Histórico</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Ajuda de comandos</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Aviso de plugin</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Modo de disposição</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Opacidade</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Comportamento de redimensionamento</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Abertura automática de tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Barra lateral</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Marca</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Ligações</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrações</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Créditos</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licença</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Clique num botão e depois prima a combinação de teclas. Esc limpa.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Ir para o separador seguinte</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Ir para o separador anterior</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Mudar reconstrói o atlas de tipos de letra, por isso o chat fica vazio por um instante.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>Relógio de 24 horas</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Mostrar histórico de sessões anteriores</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Desligado, o registo começa vazio a cada início do jogo e só se enche com as mensagens recebidas a partir daí.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Lado da ajuda de comandos</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>De que lado a lista de sugestões aparece enquanto escreve.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Modo de abertura automática de tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Onde um tell abre quando chega.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Mudar para o separador a cada tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Caso contrário, o separador abre em segundo plano após o primeiro.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Barra lateral</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Separadores no topo</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Posição dos separadores</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Onde a lista de separadores fica na janela principal.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Mostrar barra de título</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Mostrar barra de título nas janelas destacadas</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Permitir mover</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Permitir redimensionar</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Limite de troca automática da barra lateral</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Abaixo desta largura a barra lateral passa a separadores no topo, em píxeis.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Posição da pré-visualização</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Mostrar a pré-visualização apenas ao escrever</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Repositório Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifesto do repositório personalizado</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Tema ativo: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Bifurcar e editar</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Os temas integrados não podem ser editados diretamente. Bifurcar cria uma cópia personalizada que pode editar e guardar.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Editar tema</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>A editar: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Superfícies</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Contornos</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Texto</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identidade</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Estado</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Guardar</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Cancelar</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Repor para o original</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Não é possível repor enquanto edita uma bifurcação. Guarde ou cancele primeiro.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Guarde ou descarte primeiro as suas alterações</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Personalizados ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Bifurcar o tema ativo</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importar ficheiro de tema…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Caminho do ficheiro JSON (ou arraste para a pasta)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Exportar tema</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Frios</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturais</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Clássicos</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (incluída)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Tipo de letra do jogo</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Global: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Ativo: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Escreva uma mensagem...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplicar</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>pré-visualização</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>manutenção</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} separador</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} separadores</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} sussurro</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} sussurros</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} msg</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k msg</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Campeão» Pré-visualização</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>aberto</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Sem sessão iniciada</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Mais ações</value>
</data>
</root>
+351 -145
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Safety net for ChatTypes added by future FFXIV patches that the plugin does not yet know about. Default is OFF (data minimisation). Enable if you want future channels to be fully logged as well.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Apply filter to existing database</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>The privacy filter only affects new messages. The cleanup below lets you retroactively remove already-stored messages that do not match your saved whitelist.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Cleanup uses your SAVED whitelist (Plugin.Config), not unsaved changes above. Click Save first if you want your current changes to be applied.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>The manual run uses your SAVED retention policy, not the slider values above. Click Save first if you want the run to apply your current changes.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Preview is stale: your whitelist has changed since the last refresh. Click Refresh to recalculate.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Apply retention now</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Runs the retention cleanup immediately using the SAVED policy. Save your changes first.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Retention cleanup running in the background…</value>
</data>
@@ -184,7 +172,7 @@
<value>Choose a starting profile. You can adjust everything later under Settings → Privacy.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Data minimisation (recommended)</value>
<value>Data minimisation</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Only your own conversations are stored: tells, party, FC, linkshells, cross-world linkshells, alliance, and ExtraChat. Public chat, NPC dialogues, and system spam are discarded at the storage level. Retention follows spec defaults (tells 365 days, own conversation channels 90 days).</value>
@@ -226,7 +214,13 @@
<value>Welcome to Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>A Chat 2 fork from Hellion Forge with privacy-aware defaults, brand-consistent visuals, and a few quality-of-life touches.</value>
<value>Your chat window, from Hellion Forge. Privacy-first out of the box, translated into 25 languages, and yours to arrange.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Plugins are a grey area in Final Fantasy XIV: Square Enix's terms of service do not cover them, and Naoki Yoshida has publicly asked that people not advertise them. Keep the subject out of Say, Yell, Shout and every other public channel.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat started out as a fork of Chat 2. The two have drifted far enough apart since that the codebases are no longer compatible.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Three short steps. You can change everything later under Settings → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>What gets stored?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = recommended for most players.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Recommended</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Visual</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Load previous session on startup</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Apply filters to messages from previous sessions</value>
</data>
@@ -313,14 +304,11 @@
<value>(unchanged)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Try it: type /tell &lt;Player Name&gt; into chat. Hellion Chat opens a dedicated tab for the conversation and preloads the last {0} messages.</value>
<value>Try it: type /tell &lt;Player Name&gt; into chat. Hellion Chat opens a dedicated tab for the conversation and preloads the last {0} messages.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Settings → Hellion Chat to fine-tune later</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Export (GDPR Art. 15 — Right of access)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Export stored messages as Markdown, JSON, or CSV. This lets you fulfil an access request from a person whose messages you have stored, or take your own history with you.</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 community translators (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Active tells</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Unpin Tab</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Promote to permanent</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Turns this TempTell into a regular tab. The tell binding to the partner is dropped. The tab will catch messages by its channel filters from now on. For "tab survives relog while staying bound to this partner", use Pin Tab instead.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Pinned tabs survive relog and stay bound to this conversation partner.</value>
</data>
@@ -504,7 +486,7 @@
<value>Pinned: survives relog.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Note: If XIV Messenger or a similar plugin suppresses tells, disable the "Suppress DMs" option there so that Hellion Chat can receive tells and open the auto-tabs.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Tell history in auto-tabs</value>
</data>
@@ -559,15 +541,9 @@
<value>Only takes effect when auto-tell tabs are enabled in the Chat tab.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Settings restructured</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 has restructured the settings into thematic tabs. Your chat database and message history remain unchanged. Settings have been reset to defaults. If you want to re-select your privacy profile, the Reopen button is in the Privacy tab. A backup of the previous config is located at HellionChat.json.pre-v10-backup next to the active config file.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>General</value>
</data>
@@ -590,7 +566,7 @@
<value>About</value>
</data>
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -604,11 +580,11 @@
<value>Timestamps</value>
</data>
<!-- Hellion Chat — Window tab section headings (pre-cycle legacy, kept for reference) -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Window frame</value>
</data>
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Show symbol-picker button next to chat input</value>
</data>
@@ -616,21 +592,15 @@
<value>Adds a small button left of the channel indicator that opens a popup with FFXIV icons and a curated symbol list. Disable if you prefer a leaner input bar.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Storage</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Overview</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Maintenance</value>
</data>
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>System</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -647,7 +617,7 @@
<value>If you use multiple linkshells, the maintainer recommends one tab per shell for a cleaner overview. Duplicate the tab and restrict the channel selection in each copy.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Tab icon</value>
</data>
@@ -693,24 +663,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Moves the chat window and all active pop-outs back to the top-left corner of the primary monitor. Useful when a window has ended up outside the visible area after a display layout change (monitor disconnected, resolution changed). The plugin also performs an automatic bounds check once per session; this button is the manual escape hatch if something still ends up unreachable.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>New in v0.6.0: You can now type directly in pop-outs. Enable the master switch in the Window settings.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Got it</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Open window settings</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>You can open any chat tab as its own window. Click the window icon in the top right or right-click the tab. New in v0.6.1: pop-out input is active by default (can be disabled under Settings → Window).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Got it</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Open settings</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat cannot start while Chat 2 is loaded.</value>
</data>
@@ -720,54 +672,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Disable Chat 2 in /xlplugins, then re-enable Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>General</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Language, input, audio, and performance.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Appearance</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Window opacity, fonts, motion</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Choose a theme or import your own</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Window</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>When the window is visible and whether it can be moved.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, preview, message behaviour, and emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Tabs</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Create and configure custom chat tabs.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Database</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Storage, migration, legacy cleanup</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>About</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Extensions, version, project info, translators, and changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -810,9 +714,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Data &amp; Privacy</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Privacy filter, retention, cleanup, export, and database statistics.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -849,9 +750,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Advanced (Shift+click to open)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 has reorganised the settings menu and removed the old "Override style" option (superseded by the theme system from 1.1.0). Your remaining settings are unchanged. Window transparency has been migrated to "Theme &amp; Layout". A backup of the previous config is located at pluginConfigs/HellionChat.json.pre-v16-backup next to the active HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Plugin integrations let HellionChat work together with other installed Dalamud plugins. Each integration automatically detects its target and silently disables itself when the target plugin is missing.</value>
</data>
@@ -961,7 +859,7 @@
<value>Disables the theme crossfade, the sidebar and card-row hover animations, and the unread-tab pulse. Theme switches and hover states apply instantly instead.</value>
</data>
<!-- Failed-tell notification -->
<data name="FailedTell_Notification_Generic" xml:space="preserve">
<value>A tell could not be delivered.</value>
</data>
@@ -975,7 +873,7 @@
<value>Show a toast when a tell you sent could not be delivered (recipient offline, in an instance, or blocking you).</value>
</data>
<!-- Per-tab notification sound -->
<data name="Tabs_NotificationSound_Enable_Name" xml:space="preserve">
<value>Notification sound</value>
</data>
@@ -992,7 +890,7 @@
<value>Hellion sound</value>
</data>
<!-- Scroll-to-bottom and item/flag linking -->
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Jump to the latest message</value>
</data>
@@ -1003,7 +901,7 @@
<value>Insert linked item &lt;item&gt;</value>
</data>
<!-- v1.5.6: plugin-disclosure warning -->
<data name="Settings_Chat_NotifyPluginDisclosure_Name" xml:space="preserve">
<value>Warn before sending plugin-only symbols</value>
</data>
@@ -1014,7 +912,7 @@
<value>This message contains plugin-only symbols that other players may see as empty boxes. Press Enter again to send anyway.</value>
</data>
<!-- v1.5.6: world suffix + name format display options -->
<data name="Settings_Chat_WorldSuffix_Name" xml:space="preserve">
<value>World suffix</value>
</data>
@@ -1046,7 +944,7 @@
<value>Initials</value>
</data>
<!-- v1.5.6: inactive window opacity -->
<data name="Settings_ThemeAndLayout_WindowOpacityInactive_Name" xml:space="preserve">
<value>Inactive window opacity</value>
</data>
@@ -1054,7 +952,7 @@
<value>Background opacity of the main chat window while it is not focused. The slider above sets the focused value. A per-window override in Dalamud's window pinning menu still takes precedence over both.</value>
</data>
<!-- v1.5.6: custom sound volume -->
<data name="Settings_General_CustomSoundVolume_Name" xml:space="preserve">
<value>Custom sound volume</value>
</data>
@@ -1062,7 +960,7 @@
<value>Playback volume for the three bundled custom notification sounds. Does not affect the 16 game sounds.</value>
</data>
<!-- v1.5.6: General tab section titles (collapsible, R6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Input</value>
</data>
@@ -1079,7 +977,7 @@
<value>Which sound plays per tab is set in the Channels tab.</value>
</data>
<!-- v1.5.6: Chat tab section titles (collapsible, R6) -->
<data name="Settings_Section_Messages" xml:space="preserve">
<value>Messages</value>
</data>
@@ -1089,9 +987,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Auto-tell tabs</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Links &amp; tooltips</value>
</data>
@@ -1099,7 +994,7 @@
<value>Novice network</value>
</data>
<!-- v1.5.6: Appearance tab section titles (collapsible, R6) -->
<data name="Settings_Section_Theme" xml:space="preserve">
<value>Theme</value>
</data>
@@ -1119,7 +1014,7 @@
<value>Animations</value>
</data>
<!-- v1.5.6: Window tab collapsible section titles (R6) -->
<data name="Settings_Section_Hide" xml:space="preserve">
<value>Hide</value>
</data>
@@ -1130,7 +1025,7 @@
<value>Frame</value>
</data>
<!-- v1.5.6: Tabs tab per-tab-item sub-section titles (R6) -->
<data name="Settings_Section_Tab_Channels" xml:space="preserve">
<value>Channels</value>
</data>
@@ -1150,7 +1045,7 @@
<value>This volume applies to all tabs.</value>
</data>
<!-- v1.5.6: About tab collapsible section titles (R6) -->
<data name="Settings_Section_Extensions" xml:space="preserve">
<value>Extensions</value>
</data>
@@ -1166,4 +1061,315 @@
<data name="Settings_Section_Changelog" xml:space="preserve">
<value>Changelog</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Insert symbol</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Settings</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Hide chat (Enter to bring back)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Return this tab to the main window</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Another database operation is running: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>retention sweep</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>export</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>cleanup</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>clearing the history</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>The privacy filter is off, so every channel is stored and nothing in the database contradicts your settings. Switch the filter on and pick channels first.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>No channel is selected, so a cleanup would delete the entire history. Pick the channels you want to keep, or use the clear button if you really want everything gone.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>{0:N0} messages are stored. If you want to keep a copy, export them before clearing.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: runs the retention cleanup right now instead of waiting for the daily sweep. Deletes messages older than the limits above.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Clearing the history failed. Nothing was removed, see /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetry</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>No telemetry is collected. The plugin sends nothing about you or your usage anywhere.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Auto-translate</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>off</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Behaviour</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Keybinds</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Notifications</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Display modes</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>History</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Command help</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Plugin disclosure</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Layout mode</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Opacity</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Resize behaviour</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Tell auto-open</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Sidebar</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Brand</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Links</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrations</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Credits</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>License</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Click a button, then press the key combination. Esc clears.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Cycle to next chat tab</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Cycle to previous chat tab</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Switching rebuilds the font atlas, so the chat goes blank for a moment.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24-hour clock</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Show history from previous sessions</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Off means the log starts empty each time the game launches and only fills with messages received since.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Command help side</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Which side the command hint list appears on while typing.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Tell auto-open mode</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Where a tell opens when it arrives.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Switch to the tab on every tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Otherwise the tab opens in the background after the first one.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Sidebar</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Top tabs</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Tab placement</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Where the tab list sits in the main window.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Show title bar</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Show title bar for pop-outs</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Allow movement</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Allow resize</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Sidebar auto-switch threshold</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Below this width the sidebar folds into top tabs, in pixels.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Preview position</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Only show preview when typing</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea repository</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Custom repo manifest</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Active theme: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Fork &amp; Edit</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Built-in themes cannot be edited in place. Fork creates a custom copy you can edit and save.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Edit theme</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Editing: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Surfaces</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Borders</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Text</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identity</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Status</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Save</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Reset to source</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Reset is unavailable while editing a fork. Save or Cancel first.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Save or discard your edits first</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Custom ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Fork active theme</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Import theme file…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Path to JSON file (or drag-and-drop into the folder)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Export theme</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Cool</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Natural</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Classic</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (bundled)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>FFXIV game font</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Global: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Active: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Type a message...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplicate</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>preview</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>maintenance</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} tab</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} tabs</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} tell</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} tells</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} msg</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k msg</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Champion» Vorschau</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>open</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Not logged in</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>More actions</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Plasă de siguranță pentru tipurile ChatType adăugate de patch-uri viitoare FFXIV pe care plugin-ul nu le cunoaște încă. Implicit este DEZACTIVAT (minimizarea datelor). Activează dacă vrei ca și canalele viitoare să fie înregistrate complet.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Aplică filtrul pe baza de date existentă</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Filtrul de confidențialitate afectează doar mesajele noi. Curățarea de mai jos îți permite să elimini retroactiv mesajele deja stocate care nu corespund listei albe salvate.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Curățarea folosește lista albă SALVATĂ (Plugin.Config), nu modificările nesalvate de mai sus. Apasă Salvează întâi dacă vrei ca modificările curente să fie aplicate.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Rularea manuală folosește politica de retenție SALVATĂ, nu valorile sliderelor de mai sus. Apasă Salvează întâi dacă vrei ca rularea să aplice modificările curente.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Previzualizarea este depășită: lista albă s-a schimbat de la ultima reîmprospătare. Apasă Reîmprospătează pentru a recalcula.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Aplică retenția acum</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Rulează imediat curățarea de retenție folosind politica SALVATĂ. Salvează mai întâi modificările.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Curățare de retenție în desfășurare în fundal…</value>
</data>
@@ -184,7 +172,7 @@
<value>Alege un profil de start. Poți ajusta orice mai târziu din Setări → Confidențialitate.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Minimizarea datelor (recomandat)</value>
<value>Minimizarea datelor</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Sunt stocate doar propriile tale conversații: tells, party, FC, linkshells, cross-world linkshells, alliance și ExtraChat. Chatul public, dialogurile NPC și spam-ul de sistem sunt respinse la nivelul stocării. Retenția urmează implicite spec (tells 365 zile, canale de conversație proprii 90 zile).</value>
@@ -226,7 +214,13 @@
<value>Bun venit în Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Un fork Chat 2 de la Hellion Forge cu setări implicite orientate spre confidențialitate, aspect consecvent cu brandul și câteva îmbunătățiri de calitate a vieții.</value>
<value>Fereastra ta de chat, de la Hellion Forge. Confidențialitate din start, 25 de limbi, iar aranjarea îți aparține.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat a pornit ca un fork al Chat 2. De atunci cele două s-au îndepărtat suficient încât bazele de cod nu mai sunt compatibile.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Pluginurile sunt o zonă gri în Final Fantasy XIV: termenii de utilizare Square Enix nu le acoperă, iar Naoki Yoshida a cerut public să nu fie promovate. Ține deci subiectul departe de Say, Yell, Shout și de orice alt canal public.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Trei pași scurți. Poți schimba orice mai târziu din Setări → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Ce se stochează?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = recomandat pentru cei mai mulți jucători.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Recomandat</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Vizual</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Încarcă sesiunea anterioară la pornire</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Aplică filtrele și pe mesajele din sesiunile anterioare</value>
</data>
@@ -313,14 +304,11 @@
<value>(nemodificat)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Încearcă: tastează /tell &lt;Nume Jucător&gt; în chat. Hellion Chat deschide un tab dedicat pentru conversație și preîncarcă ultimele {0} mesaje.</value>
<value>Încearcă: tastează /tell &lt;Nume Jucător&gt; în chat. Hellion Chat deschide un tab dedicat pentru conversație și preîncarcă ultimele {0} mesaje.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Setări → Hellion Chat pentru ajustări ulterioare</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Export (GDPR Art. 15 — Dreptul de acces)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Exportă mesajele stocate ca Markdown, JSON sau CSV. Acest lucru îți permite să onorezi o cerere de acces din partea unei persoane ale cărei mesaje le-ai stocat, sau să îți iei propriul istoric cu tine.</value>
</data>
@@ -457,7 +445,7 @@
<value>Traducători comunitate Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Tell-uri active</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Dezfixează tab-ul</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Promovează la permanent</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Transformă acest TempTell într-un tab obișnuit. Legătura tell cu partenerul este eliminată: tab-ul va prinde mesaje după filtrele de canal de acum înainte. Pentru „tab supraviețuiește relog rămânând legat de acest partener", folosește Fixează tab-ul.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Tab-urile fixate supraviețuiesc relog-ului și rămân legate de acest partener de conversație.</value>
</data>
@@ -504,7 +486,7 @@
<value>Fixat: supraviețuiește relog-ului.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Notă: Dacă XIV Messenger sau un plugin similar suprimă tell-urile, dezactivează opțiunea „Suppress DMs" de acolo pentru ca Hellion Chat să poată primi tell-uri și să deschidă tab-urile automate.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Istoric tell în tab-uri automate</value>
</data>
@@ -559,15 +541,9 @@
<value>Intră în vigoare doar când tab-urile auto-tell sunt activate în tab-ul Chat.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Setări restructurate</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 a restructurat setările în tab-uri tematice. Baza ta de date de chat și istoricul mesajelor rămân nemodificate. Setările au fost resetate la valorile implicite. Dacă vrei să reselecți profilul de confidențialitate, butonul Redeschide se află în tab-ul Confidențialitate. O copie de rezervă a configurației anterioare se află la HellionChat.json.pre-v10-backup lângă fișierul de configurare activ.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>General</value>
</data>
@@ -590,9 +566,9 @@
<value>Despre</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Temă</value>
</data>
@@ -606,14 +582,14 @@
<value>Marcaje de timp</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Cadru fereastră</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Arată butonul selector de simboluri lângă câmpul de chat</value>
</data>
@@ -621,23 +597,17 @@
<value>Adaugă un buton mic în stânga indicatorului de canal care deschide un popup cu icoane FFXIV și o listă de simboluri curată. Dezactivează dacă preferi o bară de introducere mai simplă.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Stocare</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Prezentare generală</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Întreținere</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>System</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Dacă folosești mai multe linkshell-uri, maintainer-ul recomandă un tab per shell pentru o prezentare mai clară. Duplică tab-ul și restrânge selecția de canal în fiecare copie.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Icoană tab</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Mută fereastra de chat și toate pop-out-urile active înapoi în colțul din stânga sus al monitorului principal. Util când o fereastră a ajuns în afara zonei vizibile după o schimbare a configurației de afișaj (monitor deconectat, rezoluție schimbată). Plugin-ul efectuează și o verificare automată a limitelor o dată per sesiune; acest buton este ieșirea manuală de urgență dacă ceva tot rămâne inaccesibil.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Nou în v0.6.0: Poți scrie direct în pop-out-uri. Activează comutatorul principal din setările Fereastră.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Am înțeles</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Deschide setările ferestrei</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Poți deschide orice tab de chat ca propria fereastră. Apasă pe icoana de fereastră din dreapta sus sau clic dreapta pe tab. Nou în v0.6.1: introducerea în pop-out este activă implicit (poate fi dezactivată din Setări → Fereastră).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Am înțeles</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Deschide setările</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat nu poate porni cât timp Chat 2 este încărcat.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Dezactivează Chat 2 în /xlplugins, apoi reactivează Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>General</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Limbă, introducere, audio și performanță.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Aspect</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Opacitate fereastră, fonturi, mișcare</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Teme</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Alege o temă sau importă propria ta temă</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Fereastră</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Când fereastra este vizibilă și dacă poate fi mutată.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chat</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tell-uri, previzualizare, comportament mesaje și emote-uri.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Tab-uri</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Creează și configurează tab-uri de chat personalizate.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Bază de date</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Stocare, migrare, curățare veche</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Despre</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Extensii, versiune, informații despre proiect, traducători și changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Teme</value>
</data>
@@ -803,7 +707,7 @@
<value>Păstrează</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Confidențialitate întâi</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Deschis</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Date și confidențialitate</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Filtru de confidențialitate, retenție, curățare, export și statistici bază de date.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Temă</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Avansat (Shift+clic pentru deschidere)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 a reorganizat meniul de setări și a eliminat vechea opțiune „Override style" (înlocuită de sistemul de teme din 1.1.0). Setările tale rămase sunt nemodificate. Transparența ferestrei a fost migrată la „Temă &amp; aspect". O copie de rezervă a configurației anterioare se află la pluginConfigs/HellionChat.json.pre-v16-backup lângă fișierul activ HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Integrările de plugin-uri permit HellionChat să colaboreze cu alte plugin-uri Dalamud instalate. Fiecare integrare își detectează automat ținta și se dezactivează în liniște când plugin-ul țintă lipsește.</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Introducere</value>
</data>
@@ -999,9 +897,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>File tell automate</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emote-uri</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Linkuri și sugestii</value>
</data>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Acest mesaj conține simboluri exclusiv plugin pe care alți jucători le-ar putea vedea ca casete goale. Apasă Enter din nou pentru a trimite oricum.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Inserează un simbol</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Setări</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Ascunde chatul (Enter îl readuce)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Readu această filă în fereastra principală</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Rulează deja o altă operațiune pe baza de date: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>curățarea după perioada de păstrare</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>export</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>curățare</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>ștergerea istoricului</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Filtrul de confidențialitate este oprit, deci fiecare canal este salvat și nimic din baza de date nu contrazice setările tale. Pornește mai întâi filtrul și alege canalele.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Niciun canal nu este selectat, deci o curățare ar șterge tot istoricul. Alege canalele pe care vrei să le păstrezi sau folosește butonul de ștergere dacă chiar vrei să dispară tot.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Sunt salvate {0:N0} mesaje. Dacă vrei să păstrezi o copie, exportă-le înainte de ștergere.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: rulează curățarea acum, în loc să aștepte trecerea zilnică. Șterge mesajele mai vechi decât limitele de mai sus.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Ștergerea istoricului a eșuat. Nu a fost eliminat nimic, vezi /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetrie</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Nu se colectează telemetrie. Pluginul nu trimite nimic despre tine sau despre utilizarea ta nicăieri.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Traducere automată</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Salt la cel mai recent mesaj</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Inserează marcajul hărții &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Inserează obiectul legat &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>dezactivat</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Comportament</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Scurtături</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Notificări</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Moduri de afișare</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Istoric</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Ajutor pentru comenzi</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Notificare privind pluginul</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Mod de aranjare</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Opacitate</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Comportament la redimensionare</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Deschidere automată a tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Bară laterală</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Marcă</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Linkuri</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrări</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Credite</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licență</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Fă clic pe un buton, apoi apasă combinația de taste. Esc șterge.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Treci la tab-ul următor</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Treci la tab-ul anterior</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Schimbarea reconstruiește atlasul de fonturi, deci chatul rămâne gol o clipă.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>Ceas de 24 de ore</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Afișează istoricul din sesiunile anterioare</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Dezactivat, jurnalul pornește gol la fiecare lansare a jocului și se umple doar cu mesajele primite ulterior.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Partea ajutorului pentru comenzi</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>În ce parte apare lista de sugestii în timp ce scrii.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Mod de deschidere automată a tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Unde se deschide un tell când sosește.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Comută pe tab la fiecare tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Altfel tab-ul se deschide în fundal după primul.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Bară laterală</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Tab-uri sus</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Poziția tab-urilor</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Unde stă lista de tab-uri în fereastra principală.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Afișează bara de titlu</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Afișează bara de titlu la ferestrele desprinse</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Permite mutarea</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Permite redimensionarea</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Pragul de comutare automată a barei laterale</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Sub această lățime bara laterală se pliază în tab-uri sus, în pixeli.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Poziția previzualizării</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Afișează previzualizarea doar în timp ce scrii</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Depozit Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifest depozit personalizat</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Tema activă: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Ramifică și editează</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Temele integrate nu pot fi editate direct. Ramificarea creează o copie personalizată pe care o poți edita și salva.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Editează tema</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Se editează: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Suprafețe</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Margini</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Text</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identitate</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Stare</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Salvează</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Anulează</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Resetează la sursă</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Resetarea nu este disponibilă în timpul editării unei ramificații. Salvează sau anulează mai întâi.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Salvează sau renunță mai întâi la modificări</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Personalizate ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Ramifică tema activă</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importă fișier de temă…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Calea către fișierul JSON (sau trage-l în folder)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Exportă tema</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Reci</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturale</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Clasice</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (inclusă)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Fontul jocului</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Global: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Activ: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Scrie un mesaj...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplică</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>previzualizare</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>întreținere</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} tab</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} tab-uri</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} tell</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} tell-uri</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} mes.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k mes.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Campion» Previzualizare</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>deschis</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Neconectat</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Mai multe acțiuni</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Страховочная сеть для типов ChatType, добавленных в будущих патчах FFXIV, которые плагин ещё не знает. По умолчанию ВЫКЛ (минимизация данных). Включите, если хотите, чтобы будущие каналы тоже полностью логировались.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Применить фильтр к существующей базе данных</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Фильтр конфиденциальности действует только на новые сообщения. Очистка ниже позволяет ретроактивно удалить уже сохранённые сообщения, не соответствующие вашему сохранённому белому списку.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Очистка использует СОХРАНЁННЫЙ белый список (Plugin.Config), а не несохранённые изменения выше. Нажмите «Сохранить» сначала, если хотите применить текущие изменения.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Ручной запуск использует СОХРАНЁННУЮ политику хранения, а не значения слайдеров выше. Нажмите «Сохранить» сначала, если хотите применить текущие изменения.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Предпросмотр устарел — ваш белый список изменился с момента последнего обновления. Нажмите «Обновить» для пересчёта.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Применить хранение сейчас</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Немедленно запускает очистку по хранению, используя СОХРАНЁННУЮ политику. Сначала сохраните изменения.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Очистка по хранению выполняется в фоне…</value>
</data>
@@ -184,7 +172,7 @@
<value>Выберите начальный профиль. Всё можно изменить позже в разделе Настройки → Конфиденциальность.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Минимизация данных (рекомендуется)</value>
<value>Минимизация данных</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Сохраняются только ваши собственные разговоры: ЛС, группа, свободная компания, Linkshells, межмировые Linkshells, альянс и ExtraChat. Публичный чат, диалоги NPC и системный спам отбрасываются на уровне хранения. Сроки хранения соответствуют значениям по умолчанию (ЛС — 365 дней, собственные каналы разговора — 90 дней).</value>
@@ -226,7 +214,13 @@
<value>Добро пожаловать в Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Форк Chat 2 от Hellion Forge с настройками конфиденциальности по умолчанию, фирменным оформлением и рядом улучшений удобства использования.</value>
<value>Твоё окно чата от Hellion Forge. Приватность по умолчанию, 25 языков, и раскладка полностью в твоих руках.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat начинался как форк Chat 2. С тех пор проекты разошлись настолько, что кодовые базы больше не совместимы.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Плагины в Final Fantasy XIV находятся в серой зоне: условия использования Square Enix их не охватывают, а Наоки Ёсида публично просил не рекламировать их. Не поднимай эту тему в каналах Сказать, Вопль, Крик и любых других публичных.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Три коротких шага. Всё можно изменить позже в разделе Настройки → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Что будет сохраняться?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = рекомендуется для большинства игроков.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Рекомендовано</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Оформление</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Загружать предыдущую сессию при запуске</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Применять фильтры к сообщениям из предыдущих сессий</value>
</data>
@@ -313,14 +304,11 @@
<value>(без изменений)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Попробуйте: введите /tell &lt;Имя игрока&gt; в чате. Hellion Chat откроет отдельную вкладку для разговора и предзагрузит последние {0} сообщений.</value>
<value>Попробуйте: введите /tell &lt;Имя игрока&gt; в чате. Hellion Chat откроет отдельную вкладку для разговора и предзагрузит последние {0} сообщений.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Настройки → Hellion Chat для тонкой настройки позже</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Экспорт (GDPR Art. 15 — Право на доступ)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Экспортируйте сохранённые сообщения в формате Markdown, JSON или CSV. Это позволяет выполнить запрос на доступ от лица, чьи сообщения вы сохранили, или забрать собственную историю.</value>
</data>
@@ -457,7 +445,7 @@
<value>Переводчики сообщества Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Активные ЛС</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Открепить вкладку</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Преобразовать в постоянную</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Превращает эту TempTell в обычную вкладку. Привязка ЛС к собеседнику снимается — вкладка будет получать сообщения по фильтрам канала. Для «вкладка переживает релог, оставаясь привязанной к собеседнику» используйте «Закрепить вкладку».</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Закреплённые вкладки переживают релог и остаются привязанными к этому собеседнику.</value>
</data>
@@ -504,7 +486,7 @@
<value>Закреплено — переживает релог.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Примечание: если XIV Messenger или похожий плагин блокирует ЛС, отключите там опцию «Suppress DMs», чтобы Hellion Chat мог получать ЛС и открывать авто-вкладки.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>История ЛС в авто-вкладках</value>
</data>
@@ -559,15 +541,9 @@
<value>Действует только если авто-вкладки ЛС включены на вкладке Чат.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Настройки реструктурированы</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 реструктурировал настройки по тематическим вкладкам. Ваша база данных чата и история сообщений остались без изменений. Настройки сброшены к значениям по умолчанию. Если вы хотите повторно выбрать профиль конфиденциальности, кнопка «Открыть снова» находится на вкладке Конфиденциальность. Резервная копия предыдущей конфигурации расположена по адресу HellionChat.json.pre-v10-backup рядом с активным файлом конфигурации.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Общие</value>
</data>
@@ -590,9 +566,9 @@
<value>О программе</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Временны́е метки</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Рамка окна</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Показывать кнопку выбора символов рядом с полем ввода чата</value>
</data>
@@ -621,23 +597,17 @@
<value>Добавляет небольшую кнопку слева от индикатора канала, открывающую всплывающее окно с иконками FFXIV и подобранным списком символов. Отключите для более компактной строки ввода.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Хранение</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Обзор</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Обслуживание</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Система</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Эмоции</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Свободная компания</value>
</data>
@@ -654,7 +624,7 @@
<value>Если вы используете несколько Linkshell, разработчик рекомендует создать отдельную вкладку для каждой — для более удобного обзора. Продублируйте вкладку и ограничьте выбор каналов в каждой копии.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Иконка вкладки</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Возвращает окно чата и все активные всплывающие окна в верхний левый угол основного монитора. Полезно, когда окно оказалось за пределами видимой области после изменения раскладки дисплея (отключён монитор, изменено разрешение). Плагин также выполняет автоматическую проверку границ один раз за сессию; эта кнопка — ручной аварийный выход, если что-то всё равно оказалось недоступным.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Новое в v0.6.0: теперь можно вводить текст прямо во всплывающих окнах. Включите главный переключатель в настройках окна.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Понятно</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Открыть настройки окна</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Любую вкладку чата можно открыть в собственном окне. Нажмите иконку окна в правом верхнем углу или кликните правой кнопкой мыши по вкладке. Новое в v0.6.1: ввод во всплывающих окнах активен по умолчанию (можно отключить в разделе Настройки → Окно).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Понятно</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Открыть настройки</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat не может запуститься, пока загружен Chat 2.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Отключите Chat 2 в /xlplugins, затем снова включите Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Общие</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Язык, ввод, звук и производительность.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Внешний вид</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Прозрачность окна, шрифты, анимации</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Темы</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Выберите тему или импортируйте свою</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Окно</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Когда окно видимо и можно ли его перемещать.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Чат</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>ЛС, предпросмотр, поведение сообщений и эмоции.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Вкладки</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Создание и настройка пользовательских вкладок чата.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>База данных</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Хранение, миграция, очистка устаревшего</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>О плагине</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Расширения, версия, информация о проекте, переводчики и changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Темы</value>
</data>
@@ -803,7 +707,7 @@
<value>Оставить</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Приватность прежде всего</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Открыто</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Данные и конфиденциальность</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Фильтр конфиденциальности, хранение, очистка, экспорт и статистика базы данных.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Дополнительно (Shift+клик для открытия)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 реорганизовал меню настроек и удалил устаревшую опцию «Override style» (заменена системой тем из версии 1.1.0). Остальные настройки не изменились. Прозрачность окна перенесена в раздел «Theme &amp; Layout». Резервная копия предыдущей конфигурации расположена по адресу pluginConfigs/HellionChat.json.pre-v16-backup рядом с активным файлом HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Интеграции плагинов позволяют HellionChat работать совместно с другими установленными плагинами Dalamud. Каждая интеграция автоматически определяет целевой плагин и тихо отключается, если тот не установлен.</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Ввод</value>
</data>
@@ -999,9 +897,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Авто-вкладки tell</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Эмоции</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Ссылки и подсказки</value>
</data>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Это сообщение содержит символы плагина, которые другие игроки могут видеть как пустые квадраты. Нажмите Enter ещё раз, чтобы всё равно отправить.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Вставить символ</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Настройки</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Скрыть чат (Enter вернёт его)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Вернуть эту вкладку в главное окно</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Уже выполняется другая операция с базой данных: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>очистка по сроку хранения</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>экспорт</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>очистка</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>удаление истории</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Фильтр конфиденциальности выключен, поэтому сохраняются все каналы и ничто в базе данных не противоречит вашим настройкам. Сначала включите фильтр и выберите каналы.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Не выбран ни один канал, поэтому очистка удалит всю историю. Выберите каналы, которые хотите сохранить, или воспользуйтесь кнопкой удаления, если действительно хотите стереть всё.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Сохранено {0:N0} сообщений. Если хотите оставить копию, экспортируйте их перед удалением.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: выполняет очистку по сроку хранения сразу, не дожидаясь ежедневного прохода. Удаляет сообщения старше указанных выше пределов.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Не удалось удалить историю. Ничего не было удалено, см. /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Телеметрия</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Телеметрия не собирается. Плагин никуда не отправляет данные о вас или о вашем использовании.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Автоперевод</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Перейти к последнему сообщению</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Вставить метку карты &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Вставить связанный предмет &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>выключено</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Поведение</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Горячие клавиши</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Уведомления</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Режимы отображения</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>История</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Справка по командам</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Уведомление о плагине</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Режим компоновки</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Непрозрачность</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Изменение размера</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Автооткрытие tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Боковая панель</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Бренд</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Ссылки</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Интеграции</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Благодарности</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Лицензия</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Нажмите кнопку, затем нажмите сочетание клавиш. Esc очищает.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Перейти к следующей вкладке</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Перейти к предыдущей вкладке</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Переключение перестраивает атлас шрифтов, поэтому чат ненадолго пустеет.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24-часовой формат</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Показывать историю прошлых сеансов</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Выключено: журнал начинается пустым при каждом запуске игры и заполняется только сообщениями, полученными после.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Сторона справки по командам</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>С какой стороны появляется список подсказок при вводе.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Режим автооткрытия tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Где открывается tell при получении.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Переключаться на вкладку при каждом tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Иначе вкладка после первого открывается в фоне.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Боковая панель</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Вкладки сверху</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Расположение вкладок</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Где в главном окне находится список вкладок.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Показывать заголовок окна</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Показывать заголовок в отдельных окнах</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Разрешить перемещение</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Разрешить изменение размера</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Порог автопереключения боковой панели</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Ниже этой ширины боковая панель сворачивается во вкладки сверху, в пикселях.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Положение предпросмотра</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Показывать предпросмотр только при вводе</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Репозиторий Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Манифест пользовательского репозитория</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Активная тема: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Ответвить и изменить</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Встроенные темы нельзя изменить напрямую. Ответвление создаёт собственную копию, которую можно изменить и сохранить.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Изменить тему</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Изменяется: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Поверхности</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Границы</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Текст</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Идентичность</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Состояние</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Сохранить</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Отмена</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Вернуть к исходной</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Сброс недоступен во время правки ответвления. Сначала сохраните или отмените.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Сначала сохраните или отмените изменения</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Свои ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Ответвить активную тему</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Импортировать файл темы…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Путь к файлу JSON (или перетащите его в папку)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Экспорт темы</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Холодные</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Природные</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Классические</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Ретро</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (в комплекте)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Игровой шрифт</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Общий: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Активный: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Введите сообщение...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Дублировать</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>предпросмотр</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>обслуживание</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} вкладка</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} вкладок</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} шёпот</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} шёпотов</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} сообщ.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k сообщ.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Чемпион» Предпросмотр</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>открыт</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Вход не выполнен</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Другие действия</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Säkerhetsnät för ChatTypes som läggs till av framtida FFXIV-patchar och som pluginen ännu inte känner till. Standard är AV (dataminimering). Aktivera om du vill att framtida kanaler också loggas fullt ut.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Tillämpa filter på befintlig databas</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Sekretessfiltret påverkar bara nya meddelanden. Rensningen nedan låter dig retroaktivt ta bort redan sparade meddelanden som inte matchar din sparade vitlista.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Rensningen använder din SPARADE vitlista (Plugin.Config), inte osparade ändringar ovan. Klicka Spara först om du vill att dina aktuella ändringar ska tillämpas.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Den manuella körningen använder din SPARADE lagringspolicy, inte skjutreglagevärdena ovan. Klicka Spara först om du vill att körningen ska tillämpa dina aktuella ändringar.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Förhandsgranskningen är inaktuell: din vitlista har ändrats sedan senaste uppdateringen. Klicka Uppdatera för att räkna om.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Tillämpa lagring nu</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Kör lagringsrensningen omedelbart med den SPARADE policyn. Spara dina ändringar först.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Lagringsrensning pågår i bakgrunden…</value>
</data>
@@ -184,7 +172,7 @@
<value>Välj en startprofil. Du kan justera allt senare under Inställningar → Sekretess.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Dataminimering (rekommenderas)</value>
<value>Dataminimering</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Bara dina egna konversationer sparas: tells, grupp, FC, linkshells, flervärlds-linkshells, allians och ExtraChat. Offentlig chatt, NPC-dialoger och systemskräp kasseras på lagringsnivå. Lagring följer spec-standarder (tells 365 dagar, egna konversationskanaler 90 dagar).</value>
@@ -226,7 +214,13 @@
<value>Välkommen till Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>En Chat 2-fork från Hellion Forge med sekretessmedvetna standardinställningar, konsekvent varumärkesutseende och några livskvalitetsförbättringar.</value>
<value>Ditt chattfönster från Hellion Forge. Integritet från första start, 25 språk, och du ställer in det som du vill.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat började som en fork av Chat 2. De två har sedan dess glidit isär så mycket att kodbaserna inte längre är kompatibla.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Plugins är en gråzon i Final Fantasy XIV: Square Enix användarvillkor täcker dem inte, och Naoki Yoshida har offentligt bett om att man inte gör reklam för dem. Håll därför ämnet borta från Säg, Skrik, Ropa och alla andra offentliga kanaler.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Tre korta steg. Du kan ändra allt senare under Inställningar → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Vad sparas?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = rekommenderas för de flesta spelare.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Rekommenderad</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Utseende</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Läs in föregående session vid start</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Tillämpa filter på meddelanden från tidigare sessioner</value>
</data>
@@ -313,14 +304,11 @@
<value>(oförändrat)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Prova: skriv /tell &lt;Spelarnamn&gt; i chatten. Hellion Chat öppnar en dedikerad flik för konversationen och förladdar de senaste {0} meddelandena.</value>
<value>Prova: skriv /tell &lt;Spelarnamn&gt; i chatten. Hellion Chat öppnar en dedikerad flik för konversationen och förladdar de senaste {0} meddelandena.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Inställningar → Hellion Chat för att finjustera senare</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Export (GDPR Art. 15 — Rätt till tillgång)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Exportera sparade meddelanden som Markdown, JSON eller CSV. Det här låter dig uppfylla en begäran om tillgång från en person vars meddelanden du har sparat, eller ta med din egen historik.</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 community-översättare (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Aktiva tells</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Lossa flik</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Uppgradera till permanent</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Omvandlar den här TempTell-fliken till en vanlig flik. Bindningen till konversationspartnern tas bort och fliken fångar meddelanden via sina kanalfilter från och med nu. Använd Fäst flik om du vill att fliken ska överleva omloggning och ändå vara bunden till den här partnern.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Fästa flikar överlever omloggning och är kvar bundna till den här konversationspartnern.</value>
</data>
@@ -504,7 +486,7 @@
<value>Fäst: överlever omloggning.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Notering: Om XIV Messenger eller ett liknande plugin undertrycker tells, inaktivera alternativet "Suppress DMs" där så att Hellion Chat kan ta emot tells och öppna auto-flikar.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Tell-historik i auto-flikar</value>
</data>
@@ -559,15 +541,9 @@
<value>Träder bara i kraft när auto-tell-flikar är aktiverade i fliken Chatt.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Inställningar omstrukturerade</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 har omstrukturerat inställningarna i tematiska flikar. Din chattdatabas och meddelandehistorik är oförändrade. Inställningarna har återställts till standardvärden. Om du vill välja om din sekretesprofil finns Återöppna-knappen i fliken Sekretess. En säkerhetskopia av den tidigare konfigurationen finns vid HellionChat.json.pre-v10-backup bredvid den aktiva konfigurationsfilen.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Allmänt</value>
</data>
@@ -590,9 +566,9 @@
<value>Om</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Tidsstämplar</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Fönsterram</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Visa symbolväljarknapp bredvid chattinmatningen</value>
</data>
@@ -621,23 +597,17 @@
<value>Lägger till en liten knapp till vänster om kanalindikatorerna som öppnar ett popup-fönster med FFXIV-ikoner och en utvald symbollista. Inaktivera om du föredrar ett smalare inmatningsfält.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Lagring</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Översikt</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Underhåll</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>System</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Om du använder flera linkshells rekommenderar underhållaren en flik per shell för en tydligare översikt. Duplicera fliken och begränsa kanalvalet i varje kopia.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Flikikon</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Flyttar chattfönstret och alla aktiva pop-out-fönster tillbaka till det övre vänstra hörnet av primärskärmen. Användbart när ett fönster har hamnat utanför det synliga området efter en skärmlayoutändring (skärm frånkopplad, upplösning ändrad). Pluginen utför också en automatisk gränskontroll en gång per session. Den här knappen är den manuella nödutgången om något ändå hamnar oåtkomligt.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Nytt i v0.6.0: Du kan nu skriva direkt i pop-out-fönster. Aktivera huvudströmbrytaren i fönsterinställningarna.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Förstått</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Öppna fönsterinställningar</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Du kan öppna valfri chattflik som ett eget fönster. Klicka på fönsterikonen uppe till höger eller högerklicka på fliken. Nytt i v0.6.1: pop-out-inmatning är aktiv som standard (kan inaktiveras under Inställningar → Fönster).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Förstått</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Öppna inställningar</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat kan inte starta medan Chat 2 är inläst.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Inaktivera Chat 2 i /xlplugins och aktivera sedan Hellion Chat igen.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Allmänt</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Språk, inmatning, ljud och prestanda.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Utseende</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Fönsteropacitet, teckensnitt, rörelse</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Välj ett theme eller importera ett eget</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Fönster</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>När fönstret är synligt och om det kan flyttas.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Chatt</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, förhandsgranskning, meddelandebeteende och emotes.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Flikar</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Skapa och konfigurera anpassade chattflikar.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Databas</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Lagring, migrering, äldre rensning</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Om</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Tillägg, version, projektinformation, översättare och changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Behåll</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Integritet först</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Öppen</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Data och sekretess</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Sekretessfilter, lagring, rensning, export och databasstatistik.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Avancerat (Shift+klicka för att öppna)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 har omorganiserat inställningsmenyn och tagit bort det gamla alternativet "Åsidosätt stil" (ersatt av theme-systemet från 1.1.0). Dina övriga inställningar är oförändrade. Fönstrets genomskinlighet har migrerats till "Theme &amp; Layout". En säkerhetskopia av den tidigare konfigurationen finns vid pluginConfigs/HellionChat.json.pre-v16-backup bredvid den aktiva HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Plugin-integrationer låter HellionChat samarbeta med andra installerade Dalamud-plugins. Varje integration identifierar automatiskt sitt mål och inaktiverar sig tyst när målpluginen saknas.</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Inmatning</value>
</data>
@@ -999,9 +897,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Automatiska tell-flikar</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Länkar och verktygstips</value>
</data>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Det här meddelandet innehåller plugin-exklusiva symboler som andra spelare kanske ser som tomma rutor. Tryck Enter igen för att skicka ändå.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Infoga symbol</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Inställningar</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Dölj chatten (Enter tar tillbaka den)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Återför den här fliken till huvudfönstret</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>En annan databasåtgärd pågår: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>gallring enligt lagringstid</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>export</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>rensning</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>radering av historiken</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Integritetsfiltret är avstängt, så alla kanaler sparas och inget i databasen strider mot dina inställningar. Slå på filtret och välj kanaler först.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Ingen kanal är vald, så en rensning skulle radera hela historiken. Välj de kanaler du vill behålla, eller använd raderingsknappen om du verkligen vill ta bort allt.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>{0:N0} meddelanden är sparade. Vill du behålla en kopia, exportera dem innan du raderar.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: kör gallringen direkt i stället för att vänta på den dagliga körningen. Raderar meddelanden äldre än gränserna ovan.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Raderingen av historiken misslyckades. Ingenting togs bort, se /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetri</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Ingen telemetri samlas in. Detta plugin skickar ingenting om dig eller din användning någonstans.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Autoöversättning</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Hoppa till det senaste meddelandet</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Infoga kartmarkering &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Infoga länkat föremål &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>av</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Beteende</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Kortkommandon</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Aviseringar</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Visningslägen</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Historik</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Kommandohjälp</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Plugin-information</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Layoutläge</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Opacitet</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Storleksändring</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Automatisk öppning av tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Sidofält</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Varumärke</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Länkar</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Integrationer</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Medverkande</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Licens</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Klicka på en knapp och tryck sedan tangentkombinationen. Esc rensar.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Byt till nästa flik</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Byt till föregående flik</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Byte bygger om typsnittsatlasen, så chatten är tom ett ögonblick.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24-timmarsklocka</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Visa historik från tidigare sessioner</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Av innebär att loggen börjar tom vid varje spelstart och bara fylls med meddelanden som tas emot därefter.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Sida för kommandohjälp</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Vilken sida listan med kommandotips visas på medan du skriver.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Läge för automatisk öppning av tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Var en tell öppnas när den kommer.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Byt till fliken vid varje tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Annars öppnas fliken i bakgrunden efter den första.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Sidofält</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Flikar upptill</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Flikarnas placering</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Var fliklistan sitter i huvudfönstret.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Visa namnlist</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Namnlist för pop-out-fönster</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Tillåt flytt</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Tillåt storleksändring</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Tröskel för automatiskt byte av sidofält</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Under denna bredd viks sidofältet ihop till flikar upptill, i pixlar.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Förhandsgranskningens position</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Visa förhandsgranskning endast vid skrivning</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea-arkiv</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Manifest för eget arkiv</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Aktivt tema: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Förgrena och redigera</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Inbyggda teman kan inte redigeras direkt. Förgrening skapar en egen kopia som du kan redigera och spara.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Redigera tema</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Redigerar: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Ytor</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Kanter</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Text</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Identitet</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Status</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Spara</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Avbryt</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Återställ till källan</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Återställning är inte tillgänglig medan du redigerar en förgrening. Spara eller avbryt först.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Spara eller kasta dina ändringar först</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Egna ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Förgrena aktivt tema</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Importera temafil…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Sökväg till JSON-fil (eller dra och släpp i mappen)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Exportera tema</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Svala</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Naturliga</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Klassiska</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (medföljer)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Spelets typsnitt</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Global: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Aktiv: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Skriv ett meddelande...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Duplicera</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>förhandsgranskning</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>underhåll</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} flik</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} flikar</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} viskning</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} viskningar</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} medd.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k medd.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Mästare» Förhandsgranskning</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>öppen</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Inte inloggad</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Fler åtgärder</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Eklentinin henüz tanımadığı, gelecekteki FFXIV yamaları tarafından eklenen ChatType'lar için güvenlik ağı. Varsayılan KAPALI'dır (veri minimizasyonu). Gelecekteki kanalların da tam olarak loglanmasını istiyorsan etkinleştir.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Filtreyi mevcut veritabanına uygula</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Gizlilik filtresi yalnızca yeni mesajları etkiler. Aşağıdaki temizlik, kayıtlı beyaz listene uymayan önceden depolanmış mesajları geriye dönük olarak kaldırmanı sağlar.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Temizlik, yukarıdaki kaydedilmemiş değişiklikler değil KAYITLI beyaz listeni (Plugin.Config) kullanır. Mevcut değişikliklerinin uygulanmasını istiyorsan önce Kaydet'e tıkla.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Manuel çalıştırma, yukarıdaki kaydırıcı değerleri değil KAYITLI saklama politikasını kullanır. Mevcut değişikliklerinin uygulanmasını istiyorsan önce Kaydet'e tıkla.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Önizleme güncel değil: beyaz listen son yenilemeden bu yana değişti. Yeniden hesaplamak için Yenile'ye tıkla.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Saklama süresini şimdi uygula</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: KAYITLI politikayı kullanarak saklama temizliğini hemen çalıştırır. Önce değişikliklerini kaydet.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Saklama temizliği arka planda çalışıyor…</value>
</data>
@@ -184,7 +172,7 @@
<value>Bir başlangıç profili seç. Her şeyi daha sonra Ayarlar → Gizlilik altında değiştirebilirsin.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Veri minimizasyonu (önerilen)</value>
<value>Veri minimizasyonu</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Yalnızca kendi konuşmaların saklanır: tell'ler, parti, FC, linkshell'ler, cross-world linkshell'ler, alliance ve ExtraChat. Genel sohbet, NPC diyalogları ve sistem spam'i depolama düzeyinde atılır. Saklama süresi spec varsayılanlarına göre ayarlanır (tell'ler 365 gün, kendi konuşma kanalları 90 gün).</value>
@@ -226,7 +214,13 @@
<value>Hellion Chat'e hoş geldin</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Hellion Forge'dan gizlilik odaklı varsayılanlar, marka tutarlı görsel tasarım ve birkaç kullanım kolaylığı dokunuşuyla Chat 2'nin bir fork'u.</value>
<value>Hellion Forge'un sohbet penceresi. İlk açılıştan itibaren gizlilik öncelikli, 25 dilde, ve düzenini kendin kurarsın.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat, Chat 2'nin bir fork'u olarak başladı. İkisi o zamandan beri kod tabanları artık uyumlu olmayacak kadar birbirinden uzaklaştı.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Pluginler Final Fantasy XIV'te gri bir alandadır: Square Enix'in kullanım koşulları onları kapsamaz ve Naoki Yoshida bunların tanıtılmamasını açıkça rica etmiştir. Bu yüzden konuyu Say, Yell, Shout ve diğer tüm herkese açık kanalların dışında tut.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Üç kısa adım. Her şeyi daha sonra Ayarlar → Hellion Chat altında değiştirebilirsin.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Ne saklanacak?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = çoğu oyuncu için önerilen.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Önerilen</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Görsel</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Başlangıçta önceki oturumu yükle</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Önceki oturumlardan gelen mesajlara filtre uygula</value>
</data>
@@ -313,14 +304,11 @@
<value>(değiştirilmedi)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Dene: sohbete /tell &lt;Oyuncu Adı&gt; yaz. Hellion Chat konuşma için özel bir sekme açar ve son {0} mesajı önceden yükler.</value>
<value>Dene: sohbete /tell &lt;Oyuncu Adı&gt; yaz. Hellion Chat konuşma için özel bir sekme açar ve son {0} mesajı önceden yükler.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Daha sonra ince ayar için Ayarlar → Hellion Chat</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Dışa aktarma (GDPR Art. 15 — Erişim hakkı)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Saklanan mesajları Markdown, JSON veya CSV olarak dışa aktar. Bu, mesajlarını sakladığın bir kişinin erişim talebini karşılamana veya kendi geçmişini yanında götürmene olanak tanır.</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 topluluk çevirmenleri (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Aktif tell'ler</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Sekmeyi serbest bırak</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Kalıcı sekmeye yükselt</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Bu TempTell'i normal bir sekmeye dönüştürür. Kullanıcıya olan tell bağlantısı kaldırılır; sekme bundan sonra kanal filtrelerine göre mesaj yakalar. "Kullanıcıya bağlı kalarak yeniden giriş sonrası hayatta kalma" için bunun yerine Sekmeyi Sabitle'yi kullan.</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Sabitlenmiş sekmeler yeniden girişten sonra hayatta kalır ve bu konuşma ortağına bağlı kalır.</value>
</data>
@@ -504,7 +486,7 @@
<value>Sabitlenmiş: yeniden girişten sonra hayatta kalır.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Not: XIV Messenger veya benzer bir eklenti tell'leri engelliyorsa, Hellion Chat'in tell'leri alıp otomatik sekmeleri açabilmesi için oradaki "Suppress DMs" seçeneğini devre dışı bırak.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Otomatik sekmelerdeki tell geçmişi</value>
</data>
@@ -559,15 +541,9 @@
<value>Yalnızca Sohbet sekmesinde otomatik tell sekmeleri etkinleştirildiğinde geçerli olur.</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Ayarlar yeniden yapılandırıldı</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0, ayarları tematik sekmelere göre yeniden yapılandırdı. Sohbet veritabanın ve mesaj geçmişin değişmedi. Ayarlar varsayılanlara sıfırlandı. Gizlilik profilini yeniden seçmek istiyorsan, Yeniden Aç düğmesi Gizlilik sekmesindedir. Önceki yapılandırmanın yedeği, aktif yapılandırma dosyasının yanında HellionChat.json.pre-v10-backup olarak bulunmaktadır.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Genel</value>
</data>
@@ -590,9 +566,9 @@
<value>Hakkında</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -606,14 +582,14 @@
<value>Zaman damgaları</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Pencere çerçevesi</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Sohbet girişinin yanında sembol seçici düğmesini göster</value>
</data>
@@ -621,23 +597,17 @@
<value>Kanal göstergesinin soluna, FFXIV ikonları ve özenle seçilmiş bir sembol listesiyle bir açılır pencere açan küçük bir düğme ekler. Daha sade bir giriş çubuğu tercih ediyorsan devre dışı bırak.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Depolama</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Genel bakış</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Bakım</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Sistem</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Emote'lar</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Birden fazla linkshell kullanıyorsan, geliştirici daha temiz bir genel bakış için her kabuk için bir sekme kullanmanı önerir. Sekmeyi çoğalt ve her kopyada kanal seçimini kısıtla.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Sekme ikonu</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Sohbet penceresini ve tüm aktif pop-out'ları birincil monitörün sol üst köşesine geri taşır. Ekran düzeni değişikliğinden sonra (monitör bağlantısı kesildi, çözünürlük değişti) bir pencere görünür alanın dışında kaldığında kullanışlıdır. Eklenti ayrıca oturum başına bir kez otomatik sınır denetimi yapar; bu düğme, bir şey hâlâ erişilemez kalırsa kullanılacak manuel kaçış çıkışıdır.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>v0.6.0'da yeni: Artık doğrudan pop-out'larda yazabilirsin. Pencere ayarlarındaki ana anahtarı etkinleştir.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Anladım</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Pencere ayarlarını aç</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Herhangi bir sohbet sekmesini kendi penceresi olarak açabilirsin. Sağ üstteki pencere ikonuna tıkla ya da sekmeye sağ tıkla. v0.6.1'de yeni: pop-out girişi varsayılan olarak aktiftir (Ayarlar → Pencere altından devre dışı bırakılabilir).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Anladım</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Ayarları aç</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Chat 2 yüklüyken Hellion Chat başlatılamaz.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Chat 2'yi /xlplugins'te devre dışı bırak, ardından Hellion Chat'i yeniden etkinleştir.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Genel</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Dil, giriş, ses ve performans.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Görünüm</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Pencere opaklığı, yazı tipleri, hareket</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Themes</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Bir tema seç veya kendininkini içe aktar</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Pencere</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Pencerenin ne zaman görünür olduğu ve taşınıp taşınamayacağı.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Sohbet</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tell'ler, önizleme, mesaj davranışı ve emote'lar.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Sekmeler</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Özel sohbet sekmeleri oluştur ve yapılandır.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>Veritabanı</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Depolama, geçiş, eski temizlik</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Hakkında</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Eklentiler, sürüm, proje bilgileri, çevirmenler ve changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Themes</value>
</data>
@@ -803,7 +707,7 @@
<value>Koru</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Önce gizlilik</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Açık</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Veri ve gizlilik</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Gizlilik filtresi, saklama süresi, temizlik, dışa aktarma ve veritabanı istatistikleri.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Theme</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Gelişmiş (açmak için Shift+tıkla)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1, ayarlar menüsünü yeniden düzenledi ve eski "Stili geçersiz kıl" seçeneğini kaldırdı (1.1.0'daki tema sistemi tarafından yerini aldı). Kalan ayarların değişmedi. Pencere şeffaflığı "Theme &amp; Layout" bölümüne taşındı. Önceki yapılandırmanın yedeği, aktif HellionChat.json dosyasının yanında pluginConfigs/HellionChat.json.pre-v16-backup olarak bulunmaktadır.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Eklenti entegrasyonları, HellionChat'in yüklü diğer Dalamud eklentileriyle birlikte çalışmasını sağlar. Her entegrasyon hedefini otomatik olarak algılar ve hedef eklenti eksik olduğunda sessizce devre dışı kalır.</value>
</data>
@@ -955,7 +853,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Giriş</value>
</data>
@@ -998,9 +896,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Otomatik tell sekmeleri</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Emote'lar</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Bağlantılar ve araç ipuçları</value>
</data>
@@ -1145,4 +1040,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Bu mesaj, diğer oyuncuların boş kutu olarak görebileceği yalnızca plugin semboller içeriyor. Yine de göndermek için Enter'a tekrar basın.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Sembol ekle</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Ayarlar</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Sohbeti gizle (Geri getirmek için Enter)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Bu sekmeyi ana pencereye geri al</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Başka bir veritabanı işlemi çalışıyor: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>saklama temizliği</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>dışa aktarma</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>temizlik</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>geçmişin silinmesi</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Gizlilik filtresi kapalı, bu yüzden her kanal saklanıyor ve veritabanında ayarlarınızla çelişen bir şey yok. Önce filtreyi açın ve kanalları seçin.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Hiçbir kanal seçili değil, bu yüzden temizlik tüm geçmişi siler. Saklamak istediğiniz kanalları seçin veya gerçekten her şeyin gitmesini istiyorsanız silme düğmesini kullanın.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>{0:N0} ileti saklanıyor. Bir kopya tutmak istiyorsanız, silmeden önce dışa aktarın.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: günlük taramayı beklemeden saklama temizliğini hemen çalıştırır. Yukarıdaki sınırlardan daha eski iletileri siler.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Geçmiş silinemedi. Hiçbir şey kaldırılmadı, /xllog kaydına bakın.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Telemetri</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Hiçbir telemetri toplanmıyor. Eklenti sizinle veya kullanımınızla ilgili hiçbir şeyi hiçbir yere göndermiyor.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Otomatik çeviri</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>En son iletiye git</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Harita işaretini ekle &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Bağlantılı eşyayı ekle &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>kapalı</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Davranış</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Kısayol tuşları</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Bildirimler</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Görünüm modları</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Geçmiş</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Komut yardımı</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Eklenti bildirimi</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Yerleşim modu</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Opaklık</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Boyutlandırma davranışı</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Tell'leri otomatik açma</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Kenar çubuğu</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Marka</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Bağlantılar</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Entegrasyonlar</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Katkıda bulunanlar</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Lisans</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Bir düğmeye tıklayın, ardından tuş kombinasyonuna basın. Esc temizler.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Sonraki sekmeye geç</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Önceki sekmeye geç</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Değiştirmek yazı tipi atlasını yeniden oluşturur, bu yüzden sohbet bir an boşalır.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24 saat biçimi</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Önceki oturumların geçmişini göster</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Kapalıyken sohbet kaydı her oyun açılışında boş başlar ve yalnızca o andan sonra gelen iletilerle dolar.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Komut yardımı tarafı</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>Yazarken komut ipucu listesinin hangi tarafta görüneceği.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Tell otomatik açma modu</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Bir tell geldiğinde nerede açılacağı.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Her tell'de sekmeye geç</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Aksi hâlde sekme ilkinden sonra arka planda açılır.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Kenar çubuğu</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Üst sekmeler</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Sekme yerleşimi</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Sekme listesinin ana pencerede nerede duracağı.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Başlık çubuğunu göster</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Ayrık pencereler için başlık çubuğunu göster</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Taşımaya izin ver</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Boyutlandırmaya izin ver</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Kenar çubuğu otomatik geçiş eşiği</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Bu genişliğin altında kenar çubuğu üst sekmelere katlanır, piksel olarak.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Önizleme konumu</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Önizlemeyi yalnızca yazarken göster</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea deposu</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Özel depo manifesti</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Etkin tema: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Çatalla ve düzenle</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Yerleşik temalar doğrudan düzenlenemez. Çatallama, düzenleyip kaydedebileceğiniz özel bir kopya oluşturur.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Temayı düzenle</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Düzenleniyor: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Yüzeyler</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Kenarlıklar</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Metin</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Kimlik</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Durum</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Kaydet</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>İptal</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Kaynağa sıfırla</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Bir çatal düzenlenirken sıfırlama kullanılamaz. Önce kaydedin veya iptal edin.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Önce değişikliklerinizi kaydedin veya atın</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Özel ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Etkin temayı çatalla</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Tema dosyası içe aktar…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSON dosyasının yolu (veya klasöre sürükleyip bırakın)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Temayı dışa aktar</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Soğuk</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Doğal</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Klasik</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Retro</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (birlikte gelir)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Oyun yazı tipi</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Genel: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Etkin: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Bir ileti yazın...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Çoğalt</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>önizleme</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>bakım</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} sekme</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} sekme</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} tell</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} tell</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} ileti</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k ileti</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Şampiyon» Önizleme</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>açık</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Oturum açılmadı</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Diğer işlemler</value>
</data>
</root>
+352 -137
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>Страховий захід для типів ChatTypes, доданих у майбутніх патчах FFXIV, які плагін ще не знає. За замовчуванням ВИМК (мінімізація даних). Увімкніть, якщо хочете, щоб майбутні канали також повністю журналювались.</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>Застосувати фільтр до наявної бази даних</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>Фільтр конфіденційності діє лише на нові повідомлення. Очищення нижче дозволяє заднім числом видалити вже збережені повідомлення, які не відповідають збереженому білому списку.</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>Очищення використовує ЗБЕРЕЖЕНИЙ білий список (Plugin.Config), а не незбережені зміни вище. Спочатку натисніть «Зберегти», якщо хочете застосувати поточні зміни.</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>Ручний запуск використовує ЗБЕРЕЖЕНУ політику зберігання, а не значення повзунків вище. Спочатку натисніть «Зберегти», якщо хочете застосувати поточні зміни.</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>Попередній перегляд застарів — Ваш білий список змінився після останнього оновлення. Натисніть «Оновити» для перерахунку.</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>Застосувати термін зберігання зараз</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: Негайно запускає очищення за терміном зберігання, використовуючи ЗБЕРЕЖЕНУ політику. Спочатку збережіть зміни.</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>Очищення за терміном зберігання виконується у фоновому режимі…</value>
</data>
@@ -184,7 +172,7 @@
<value>Виберіть початковий профіль. Все можна налаштувати пізніше в розділі Налаштування → Конфіденційність.</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>Мінімізація даних (рекомендовано)</value>
<value>Мінімізація даних</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>Зберігаються лише Ваші власні розмови: tells, група, FC, linkshells, cross-world linkshells, альянс і ExtraChat. Публічний чат, діалоги NPC та системний спам відкидаються на рівні зберігання. Термін зберігання за стандартними значеннями специфікації (tells — 365 днів, канали власних розмов — 90 днів).</value>
@@ -226,7 +214,13 @@
<value>Ласкаво просимо до Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Форк Chat 2 від Hellion Forge з урахуванням конфіденційності, фірмовим оформленням та кількома зручними покращеннями.</value>
<value>Твоє вікно чату від Hellion Forge. Приватність за замовчуванням, 25 мов, і розкладка цілком у твоїх руках.</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat починався як форк Chat 2. Відтоді проєкти розійшлися настільки, що кодові бази більше не сумісні.</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>Плагіни у Final Fantasy XIV перебувають у сірій зоні: умови використання Square Enix їх не охоплюють, а Наокі Йосіда публічно просив не рекламувати їх. Не піднімай цю тему в каналах Say, Yell, Shout та будь-яких інших публічних.</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>Три коротких кроки. Все можна змінити пізніше в розділі Налаштування → Hellion Chat.</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>Що зберігається?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = рекомендовано для більшості гравців.</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>Рекомендовано</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>Зовнішній вигляд</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>Завантажувати попередній сеанс при запуску</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>Застосовувати фільтри до повідомлень з попередніх сеансів</value>
</data>
@@ -313,14 +304,11 @@
<value>(без змін)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 Спробуйте: введіть /tell &lt;Ім'я гравця&gt; у чат. Hellion Chat відкриє окрему вкладку для розмови й попередньо завантажить останні {0} повідомлень.</value>
<value>Спробуйте: введіть /tell &lt;Ім'я гравця&gt; у чат. Hellion Chat відкриє окрему вкладку для розмови й попередньо завантажить останні {0} повідомлень.</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>Налаштування → Hellion Chat для подальшого тонкого налаштування</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>Експорт (GDPR Art. 15 — Право доступу)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>Експорт збережених повідомлень у форматі Markdown, JSON або CSV. Це дозволяє виконати запит на доступ від особи, чиї повідомлення Ви зберегли, або взяти власну історію з собою.</value>
</data>
@@ -457,7 +445,7 @@
<value>Перекладачі спільноти Chat 2 (upstream)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>Активні tells</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>Відкріпити вкладку</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>Перетворити на постійну</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>Перетворює цей TempTell на звичайну вкладку. Прив'язка tell до партнера знімається — вкладка надалі отримуватиме повідомлення за фільтрами каналів. Для «вкладка виживає після релогу та залишається прив'язаною до цього партнера» натомість скористайтесь «Закріпити вкладку».</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>Закріплені вкладки виживають після релогу та залишаються прив'язаними до цього партнера розмови.</value>
</data>
@@ -504,7 +486,7 @@
<value>Закріплено — виживає після релогу.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
</data>
@@ -545,7 +527,7 @@
<value>Примітка: якщо XIV Messenger або подібний плагін пригнічує tells, вимкніть там опцію «Suppress DMs», щоб Hellion Chat міг отримувати tells і відкривати авто-вкладки.</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Історія tells в авто-вкладках</value>
</data>
@@ -559,15 +541,9 @@
<value>Діє лише тоді, коли авто-tell-вкладки увімкнено на вкладці «Чат».</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>Налаштування реструктуровано</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 реструктурував налаштування на тематичні вкладки. База даних чату та історія повідомлень залишились без змін. Налаштування скинуто до стандартних. Якщо Ви хочете повторно вибрати профіль конфіденційності, кнопка «Показати знову» знаходиться на вкладці «Конфіденційність». Резервна копія попередньої конфігурації знаходиться за адресою HellionChat.json.pre-v10-backup поруч із активним конфігураційним файлом.</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>Загальні</value>
</data>
@@ -590,9 +566,9 @@
<value>Про плагін</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>Тема</value>
</data>
@@ -606,14 +582,14 @@
<value>Мітки часу</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>Рамка вікна</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>Показувати кнопку вибору символів поруч із полем введення чату</value>
</data>
@@ -621,23 +597,17 @@
<value>Додає невелику кнопку ліворуч від індикатора каналу, що відкриває спливаюче вікно з іконками FFXIV і підібраним списком символів. Вимкніть, якщо надаєте перевагу більш компактній панелі введення.</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>Зберігання</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>Огляд</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>Обслуговування</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>Система</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>Емоти</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>Free Company</value>
</data>
@@ -654,7 +624,7 @@
<value>Якщо Ви використовуєте кілька linkshells, розробник рекомендує по одній вкладці на кожну для зручнішого огляду. Продублюйте вкладку й обмежте вибір каналів у кожній копії.</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>Іконка вкладки</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>Переміщує вікно чату та всі активні спливаючі вікна назад у верхній лівий кут основного монітора. Корисно, коли вікно опинилось поза видимою областю після зміни конфігурації дисплея (монітор від'єднано, змінено роздільну здатність). Плагін також виконує автоматичну перевірку меж один раз за сеанс; ця кнопка є ручним запасним виходом, якщо щось все одно залишається недоступним.</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>Нове у v0.6.0: тепер можна вводити текст безпосередньо у спливаючих вікнах. Увімкніть головний перемикач у налаштуваннях вікна.</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>Зрозуміло</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>Відкрити налаштування вікна</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>Будь-яку вкладку чату можна відкрити як окреме вікно. Натисніть іконку вікна у верхньому правому куті або клацніть правою кнопкою миші по вкладці. Нове у v0.6.1: введення у спливаючих вікнах активне за замовчуванням (можна вимкнути в розділі Налаштування → Вікно).</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>Зрозуміло</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>Відкрити налаштування</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat не може запуститись, поки завантажено Chat 2.</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>Вимкніть Chat 2 у /xlplugins, а потім знову увімкніть Hellion Chat.</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>Загальні</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>Мова, введення, звук і продуктивність.</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>Зовнішній вигляд</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>Непрозорість вікна, шрифти, анімація</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>Теми</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>Вибрати тему або імпортувати власну</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>Вікно</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>Коли вікно видиме та чи можна його переміщати.</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>Чат</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>Tells, попередній перегляд, поведінка повідомлень та емоції.</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>Вкладки</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>Створення та налаштування власних вкладок чату.</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>База даних</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>Зберігання, міграція, видалення застарілого</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>Про плагін</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>Розширення, версія, інформація про проект, перекладачі та changelog.</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>Теми</value>
</data>
@@ -803,7 +707,7 @@
<value>Залишити</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>Приватність передусім</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>Відкрито</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>Дані та конфіденційність</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>Фільтр конфіденційності, термін зберігання, очищення, експорт та статистика бази даних.</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>Тема</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>Додаткові параметри (Shift+клік для відкриття)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 реорганізував меню налаштувань і видалив стару опцію «Перевизначити стиль» (замінена системою тем із версії 1.1.0). Решта налаштувань залишилась без змін. Прозорість вікна перенесена до розділу «Тема &amp; Макет». Резервна копія попередньої конфігурації знаходиться за адресою pluginConfigs/HellionChat.json.pre-v16-backup поруч із активним HellionChat.json.</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>Інтеграції плагінів дозволяють HellionChat взаємодіяти з іншими встановленими плагінами Dalamud. Кожна інтеграція автоматично визначає свою ціль і тихо вимикається, якщо цільовий плагін відсутній.</value>
</data>
@@ -955,7 +853,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>Введення</value>
</data>
@@ -998,9 +896,6 @@
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>Автоматичні вкладки tell</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>Емоції</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>Посилання та підказки</value>
</data>
@@ -1145,4 +1040,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>Це повідомлення містить символи плагіна, які інші гр��вці можуть бачити як порожні квадрати. Натисніть Enter ще раз, щоб надіслати все одно.</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>Вставити символ</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>Налаштування</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>Сховати чат (Enter поверне його)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>Повернути цю вкладку до головного вікна</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>Уже виконується інша операція з базою даних: {0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>очищення за строком зберігання</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>експорт</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>очищення</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>видалення історії</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>Фільтр приватності вимкнено, тому зберігаються всі канали і ніщо в базі даних не суперечить вашим налаштуванням. Спершу увімкніть фільтр і виберіть канали.</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>Не вибрано жодного каналу, тому очищення видалить усю історію. Виберіть канали, які хочете зберегти, або скористайтеся кнопкою видалення, якщо справді хочете стерти все.</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>Збережено {0:N0} повідомлень. Якщо хочете залишити копію, експортуйте їх перед видаленням.</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift: виконує очищення за строком зберігання одразу, не чекаючи щоденного проходу. Видаляє повідомлення, старші за вказані вище межі.</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>Не вдалося видалити історію. Нічого не було видалено, див. /xllog.</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>Телеметрія</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>Телеметрія не збирається. Плагін нікуди не надсилає дані про вас або про ваше використання.</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>Автопереклад</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>Перейти до останнього повідомлення</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>Вставити позначку карти &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>Вставити пов'язаний предмет &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>вимкнено</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>Поведінка</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>Гарячі клавіші</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>Сповіщення</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>Режими відображення</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>Історія</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>Довідка команд</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>Повідомлення про плагін</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>Режим компонування</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>Непрозорість</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>Зміна розміру</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>Автовідкриття tell</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>Бічна панель</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>Бренд</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>Посилання</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>Інтеграції</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>Подяки</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>Ліцензія</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>Натисніть кнопку, потім натисніть комбінацію клавіш. Esc очищає.</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>Перейти до наступної вкладки</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>Перейти до попередньої вкладки</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>Перемикання перебудовує атлас шрифтів, тому чат на мить порожніє.</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24-годинний формат</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>Показувати історію попередніх сеансів</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>Вимкнено: журнал починається порожнім за кожного запуску гри й заповнюється лише повідомленнями, отриманими після цього.</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>Сторона довідки команд</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>З якого боку з'являється список підказок під час введення.</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>Режим автовідкриття tell</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>Де відкривається tell, коли надходить.</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>Перемикатися на вкладку за кожного tell</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>Інакше вкладка після першого відкривається у фоні.</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>Бічна панель</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>Вкладки згори</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>Розташування вкладок</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>Де в головному вікні розташований список вкладок.</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>Показувати рядок заголовка</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>Показувати рядок заголовка у відокремлених вікнах</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>Дозволити переміщення</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>Дозволити зміну розміру</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>Поріг автоперемикання бічної панелі</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>Нижче цієї ширини бічна панель згортається у вкладки згори, у пікселях.</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>Розташування попереднього перегляду</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>Перегляд лише під час введення</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Репозиторій Gitea</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>Маніфест власного репозиторію</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>Активна тема: {0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>Відгалузити та редагувати</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>Вбудовані теми не можна редагувати напряму. Відгалуження створює власну копію, яку можна редагувати та зберегти.</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>Редагувати тему</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>Редагується: {0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>Поверхні</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>Межі</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>Текст</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>Ідентичність</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>Стан</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>Зберегти</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>Скасувати</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>Скинути до джерела</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>Скидання недоступне під час редагування відгалуження. Спершу збережіть або скасуйте.</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>Спершу збережіть або скасуйте зміни</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>Власні ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>Відгалузити активну тему</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>Імпортувати файл теми…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>Шлях до файлу JSON (або перетягніть у теку)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>Експорт теми</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>Холодні</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>Природні</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>Класичні</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>Ретро</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter (у комплекті)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>Ігровий шрифт</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>Загальний: {0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>Активний: {0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>Введіть повідомлення...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>Дублювати</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>попередній перегляд</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>обслуговування</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} вкладка</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} вкладок</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} шепіт</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} шепотів</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} повід.</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k повід.</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«Чемпіон» Перегляд</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>відкрито</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>Вхід не виконано</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>Інші дії</value>
</data>
</root>
+354 -139
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>用于兜底处理未来 FFXIV 补丁新增而插件尚未识别的 ChatType。默认为关闭(数据最小化)。如需完整记录未来新增频道,请启用此选项。</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>将过滤器应用到现有数据库</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>隐私过滤器仅对新消息生效。下方的清理功能可让你追溯删除已保存但不符合当前白名单的消息。</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>清理使用的是已保存的白名单(Plugin.Config),而非上方未保存的更改。如需应用当前更改,请先点击保存。</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>手动运行使用的是已保存的保留策略,而非上方滑块的当前值。如需应用当前更改,请先点击保存。</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>预览已过时,白名单自上次刷新后有所更改。请点击刷新以重新计算。</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>立即应用保留策略</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift:使用已保存的策略立即执行保留清理。请先保存更改。</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>保留清理正在后台运行…</value>
</data>
@@ -184,7 +172,7 @@
<value>选择一个初始配置方案。之后可在设置 → 隐私中随时调整。</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>数据最小化(推荐)</value>
<value>数据最小化</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>仅保存你自己的对话:密语、小队、部队、通讯贝、跨服通讯贝、团队以及 ExtraChat。公共聊天、NPC 对话和系统垃圾信息将在存储层直接丢弃。保留期限遵循规格默认值(密语 365 天,自有对话频道 90 天)。</value>
@@ -226,7 +214,13 @@
<value>欢迎使用 Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>来自 Hellion Forge 的 Chat 2 分支,具备隐私友好的默认设置、品牌一致的视觉风格,以及若干实用改进。</value>
<value>来自 Hellion Forge 的聊天窗口。默认即注重隐私,支持 25 种语言,界面由你自己安排。</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat 最初是 Chat 2 的分支。此后两者已相去甚远,代码库不再兼容。</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>插件在《最终幻想14》中处于灰色地带:史克威尔艾尼克斯的使用条款并未涵盖插件,吉田直树也曾公开呼吁不要宣传。请不要在说话、呼喊、喊话以及其他任何公开频道谈论此事。</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>共三个简短步骤。之后可在设置 → Hellion Chat 中随时修改。</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>保存哪些内容?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = 推荐大多数玩家使用。</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>推荐</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>Roleplay</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>视觉</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>启动时加载上次会话</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>将过滤器应用到上次会话的消息</value>
</data>
@@ -313,14 +304,11 @@
<value>(未更改)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 试一试:在聊天框输入 /tell &lt;玩家名称&gt;。Hellion Chat 会自动为该对话开启专属标签页,并预加载最近 {0} 条消息。</value>
<value>试一试:在聊天框输入 /tell &lt;玩家名称&gt;。Hellion Chat 会自动为该对话开启专属标签页,并预加载最近 {0} 条消息。</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>进入设置 → Hellion Chat 可进一步微调</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>导出(GDPR Art. 15 — 访问权)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>将已保存的消息导出为 Markdown、JSON 或 CSV 格式。可用于响应他人的数据访问请求,或将自己的聊天历史带走备份。</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 社区翻译者(上游)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>活跃密语</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>取消固定</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>提升为永久标签页</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>将此临时密语标签页转换为普通标签页。与对话伙伴的密语绑定将被解除,之后该标签页将根据频道过滤器接收消息。若需要"标签页在重新登录后仍保持与该伙伴的绑定",请使用固定标签页功能。</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>固定的标签页在重新登录后仍会保留,并保持与该对话伙伴的绑定。</value>
</data>
@@ -504,9 +486,9 @@
<value>已固定,重新登录后仍保留。</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
<value>自动密语标签页</value>
</data>
<data name="ChatLog_AutoTellTabs_Enable_Name" xml:space="preserve">
<value>为每条 /tell 自动为对话伙伴开启专属标签页</value>
@@ -545,7 +527,7 @@
<value>注意:如果 XIV Messenger 或类似插件屏蔽了密语,请在该插件中禁用"Suppress DMs"选项,以便 Hellion Chat 能正常接收密语并打开自动标签页。</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>自动标签页中的密语历史</value>
</data>
@@ -559,15 +541,9 @@
<value>仅在聊天标签页中启用了自动密语标签页时生效。</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>设置已重新整理</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 已将设置重新整理为分主题的标签页。你的聊天数据库和消息历史保持不变。设置已重置为默认值。如需重新选择隐私方案,可在隐私标签页中找到"再次显示向导"按钮。上一版配置的备份文件位于活动配置文件旁边,文件名为 HellionChat.json.pre-v10-backup。</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>通用</value>
</data>
@@ -590,9 +566,9 @@
<value>关于</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>主题</value>
</data>
@@ -606,14 +582,14 @@
<value>时间戳</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>窗口边框</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>在聊天输入框旁显示符号选取按钮</value>
</data>
@@ -621,23 +597,17 @@
<value>在频道指示器左侧添加一个小按钮,点击可打开包含 FFXIV 图标和精选符号列表的弹出窗口。如果你希望输入栏更简洁,可以禁用此功能。</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>存储</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>概览</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>维护</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>系统</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>情感动作</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>部队</value>
</data>
@@ -654,7 +624,7 @@
<value>如果你使用多个通讯贝,维护者建议为每个通讯贝单独创建一个标签页,以获得更清晰的概览。复制该标签页,并在每个副本中分别限定频道选择即可。</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>标签页图标</value>
</data>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>将聊天窗口及所有活跃的弹出窗口移回主显示器左上角。当显示器布局更改(断开显示器、更改分辨率)导致窗口超出可见区域时很有用。插件每次会话也会自动进行一次边界检查;如果仍有窗口无法访问,可使用此按钮手动修复。</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>v0.6.0 新功能:现在可以直接在弹出窗口中输入。请在窗口设置中启用主开关。</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>知道了</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>打开窗口设置</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>可以将任意聊天标签页作为独立窗口打开。点击右上角的窗口图标,或右键点击标签页即可。v0.6.1 新功能:弹出窗口输入默认已启用(可在设置 → 窗口中关闭)。</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>知道了</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>打开设置</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Chat 2 处于加载状态时 Hellion Chat 无法启动。</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>请在 /xlplugins 中禁用 Chat 2,然后重新启用 Hellion Chat。</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>通用</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>语言、输入、音频与性能。</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>外观</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>窗口不透明度、字体、动效</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>主题</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>选择主题或导入自定义主题</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>窗口</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>窗口的显示时机以及是否可移动。</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>聊天</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>密语、预览、消息行为与情感动作。</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>标签页</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>创建并配置自定义聊天标签页。</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>数据库</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>存储、迁移、历史清理</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>关于</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>扩展、版本、项目信息、译者与更新日志。</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>主题</value>
</data>
@@ -803,7 +707,7 @@
<value>保留</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>隐私优先</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>开放</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>数据与隐私</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>隐私过滤器、保留策略、清理、导出与数据库统计。</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>主题</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>高级选项(Shift+点击展开)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 已重新整理设置菜单,并移除了旧版"覆盖样式"选项(已由 1.1.0 引入的主题系统取代)。其余设置保持不变。窗口透明度已迁移至"Theme &amp; Layout"。上一版配置的备份文件位于活动 HellionChat.json 旁边,文件名为 pluginConfigs/HellionChat.json.pre-v16-backup。</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>插件集成功能让 HellionChat 能与其他已安装的 Dalamud 插件协同工作。每项集成会自动检测目标插件,目标插件缺失时将静默禁用。</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>输入</value>
</data>
@@ -997,10 +895,7 @@
<value>输入与预览</value>
</data>
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>自动Tell标签页</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>表情动作</value>
<value>自动密语标签页</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>链接与工具提示</value>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>该消息包含插件专用符号,其他玩家可能看到空白方框。再次按 Enter 键强制发送。</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>插入符号</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>设置</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>隐藏聊天(按 Enter 恢复)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>将此标签页放回主窗口</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>另一项数据库操作正在进行:{0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>保留期清理</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>导出</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>清理</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>清空历史记录</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>隐私过滤器已关闭,因此所有频道都会保存,数据库中没有与设置冲突的内容。请先开启过滤器并选择频道。</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>未选择任何频道,因此清理会删除全部历史记录。请选择要保留的频道,若确实想全部删除,请使用清空按钮。</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>已保存 {0:N0} 条消息。若想留一份副本,请在清空前先导出。</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift:立即执行保留期清理,无需等待每日运行。删除早于上方期限的消息。</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>清空历史记录失败。没有删除任何内容,请查看 /xllog。</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>遥测</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>不收集任何遥测数据。插件不会向任何地方发送关于你或你使用情况的信息。</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>自动翻译</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>跳到最新消息</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>插入地图标记 &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>插入关联物品 &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>关闭</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>行为</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>快捷键</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>通知</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>显示模式</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>历史记录</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>命令帮助</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>插件提示</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>布局模式</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>不透明度</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>调整大小行为</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>自动打开密语</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>侧边栏</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>品牌</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>链接</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>集成</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>制作人员</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>许可证</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>点击按钮后按下组合键。Esc 清除。</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>切换到下一个标签</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>切换到上一个标签</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>切换会重建字体图集,因此聊天会短暂空白。</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24 小时制</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>显示之前会话的历史记录</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>关闭时,日志在每次启动游戏时都是空的,只会填入此后收到的消息。</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>命令帮助的位置</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>输入时命令提示列表出现在哪一侧。</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>密语自动打开方式</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>密语到达时在何处打开。</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>每条密语都切换到标签</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>否则标签会在第一条之后于后台打开。</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>侧边栏</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>顶部标签</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>标签位置</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>标签列表在主窗口中的位置。</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>显示标题栏</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>显示弹出窗口的标题栏</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>允许移动</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>允许调整大小</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>侧边栏自动切换阈值</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>低于此宽度时侧边栏会折叠为顶部标签,单位为像素。</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>预览位置</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>仅在输入时显示预览</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea 仓库</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>自定义仓库清单</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>当前主题:{0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>复制并编辑</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>内置主题无法直接编辑。复制会创建一份可编辑并保存的自定义副本。</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>编辑主题</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>正在编辑:{0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>表面</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>边框</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>文本</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>身份</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>状态</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>保存</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>取消</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>重置为原始主题</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>编辑副本时无法重置。请先保存或取消。</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>请先保存或放弃你的更改</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>自定义 ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>复制当前主题</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>导入主题文件…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSON 文件路径(或拖放到文件夹)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>导出主题</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>冷色</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>自然</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>经典</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>复古</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter(内置)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>游戏字体</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>全局:{0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>使用中:{0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>输入消息...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>复制</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>预览</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>维护</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} 标签</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} 标签</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} 密语</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} 密语</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} 条</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k 条</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«冠军» 预览</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>打开</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>未登录</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>更多操作</value>
</data>
</root>
+360 -145
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version='1.0' encoding='utf-8'?>
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
@@ -63,18 +63,9 @@
<data name="Privacy_PersistUnknown_Description" xml:space="preserve">
<value>為未來 FFXIV 更新新增而插件尚未識別的 ChatType 提供安全網。預設為關閉(資料最小化)。若想讓未來的頻道也完整記錄,請啟用此選項。</value>
</data>
<data name="Cleanup_Heading" xml:space="preserve">
<value>將篩選器套用至現有資料庫</value>
</data>
<data name="Cleanup_Help_Intro" xml:space="preserve">
<value>隱私篩選器只影響新訊息。下方的清理功能讓你可以追溯刪除已儲存但不符合白名單的訊息。</value>
</data>
<data name="Cleanup_Help_SavedNote" xml:space="preserve">
<value>清理使用的是已儲存的白名單(Plugin.Config),而非上方未儲存的變更。若要套用目前的變更,請先點擊儲存。</value>
</data>
<data name="Retention_Help_SavedNote" xml:space="preserve">
<value>手動執行使用的是已儲存的保留原則,而非上方的滑桿數值。若要套用目前的變更,請先點擊儲存。</value>
</data>
<data name="Cleanup_Preview_Stale" xml:space="preserve">
<value>預覽已過時,你的白名單自上次重新整理後已有變更。點擊重新整理以重新計算。</value>
</data>
@@ -159,9 +150,6 @@
<data name="Retention_Apply_Label" xml:space="preserve">
<value>立即套用保留原則</value>
</data>
<data name="Retention_Apply_Tooltip" xml:space="preserve">
<value>Ctrl+Shift:使用已儲存的原則立即執行保留清理。請先儲存你的變更。</value>
</data>
<data name="Retention_Running" xml:space="preserve">
<value>保留清理正在背景執行中…</value>
</data>
@@ -184,7 +172,7 @@
<value>選擇一個起始設定檔。之後可在設定 → 隱私中調整所有選項。</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Heading" xml:space="preserve">
<value>資料最小化(推薦)</value>
<value>資料最小化</value>
</data>
<data name="Wizard_Profile_PrivacyFirst_Description" xml:space="preserve">
<value>只儲存你自己的對話:悄悄話、小隊、部隊、通訊貝、跨服通訊貝、團隊和 ExtraChat。公開聊天、NPC 對話和系統垃圾訊息在儲存層即被丟棄。保留期限遵循規格預設值(悄悄話 365 天,自己的對話頻道 90 天)。</value>
@@ -226,7 +214,13 @@
<value>歡迎使用 Hellion Chat</value>
</data>
<data name="Wizard_Step1_Subtitle" xml:space="preserve">
<value>Hellion Forge 推出的 Chat 2 分支版本,具備重視隱私的預設值、品牌一致的視覺設計以及一些生活品質改善。</value>
<value>來自 Hellion Forge 的聊天視窗。預設即重視隱私,支援 25 種語言,版面由你自己安排。</value>
</data>
<data name="Wizard_Step1_Heritage" xml:space="preserve">
<value>Hellion Chat 最初是 Chat 2 的分支。此後兩者已相去甚遠,程式碼庫不再相容。</value>
</data>
<data name="Wizard_Step1_PluginNotice" xml:space="preserve">
<value>外掛在《Final Fantasy XIV》中屬於灰色地帶:史克威爾艾尼克斯的使用條款並未涵蓋,吉田直樹也曾公開呼籲不要宣傳。請勿在説話、呼喊、喊話以及其他任何公開頻道談論此事。</value>
</data>
<data name="Wizard_Step1_Footer_Hint" xml:space="preserve">
<value>共三個簡短步驟。之後可在設定 → Hellion Chat 中變更所有設定。</value>
@@ -240,8 +234,8 @@
<data name="Wizard_Step2_Title" xml:space="preserve">
<value>哪些內容會被儲存?</value>
</data>
<data name="Wizard_Step2_RecommendedFooter" xml:space="preserve">
<value>★ = 推薦給大多數玩家。</value>
<data name="Wizard_Profile_Recommended_Badge" xml:space="preserve">
<value>推薦</value>
</data>
<data name="Wizard_Profile_Roleplay_Heading" xml:space="preserve">
<value>角色扮演</value>
@@ -273,9 +267,6 @@
<data name="Wizard_Step3_Section_Visual" xml:space="preserve">
<value>視覺</value>
</data>
<data name="Wizard_Step3_LoadPreviousSession_Label" xml:space="preserve">
<value>啟動時載入上次的會話</value>
</data>
<data name="Wizard_Step3_FilterIncludePreviousSessions_Label" xml:space="preserve">
<value>將篩選器套用至先前會話的訊息</value>
</data>
@@ -313,14 +304,11 @@
<value>(未變更)</value>
</data>
<data name="Wizard_Step4_TestHint" xml:space="preserve">
<value>💡 試試看:在聊天中輸入 /tell &lt;玩家名稱&gt;。Hellion Chat 會為此對話開啟專屬標籤頁,並預載最後 {0} 則訊息。</value>
<value>試試看:在聊天中輸入 /tell &lt;玩家名稱&gt;。Hellion Chat 會為此對話開啟專屬標籤頁,並預載最後 {0} 則訊息。</value>
</data>
<data name="Wizard_Step4_SettingsHint" xml:space="preserve">
<value>設定 → Hellion Chat 可在之後進行細部調整</value>
</data>
<data name="Export_Heading" xml:space="preserve">
<value>匯出(GDPR Art. 15 — 查閱權)</value>
</data>
<data name="Export_Help" xml:space="preserve">
<value>將已儲存的訊息匯出為 Markdown、JSON 或 CSV 格式。這讓你可以回應你所儲存訊息的當事人提出的查閱請求,或帶走自己的聊天歷史。</value>
</data>
@@ -457,7 +445,7 @@
<value>Chat 2 社群譯者(上游)</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Runtime strings) -->
<data name="AutoTellTabs_SectionHeader" xml:space="preserve">
<value>進行中的悄悄話</value>
</data>
@@ -479,12 +467,6 @@
<data name="PinTab_MenuUnpin" xml:space="preserve">
<value>取消釘選</value>
</data>
<data name="PinTab_MenuPromote" xml:space="preserve">
<value>升格為永久標籤頁</value>
</data>
<data name="PinTab_PromoteTooltip" xml:space="preserve">
<value>將此 TempTell 轉換為一般標籤頁。與對話對象的悄悄話綁定將解除,標籤頁之後將依頻道篩選條件接收訊息。若要「標籤頁在重新登入後保留且持續綁定此對象」,請改用釘選標籤頁。</value>
</data>
<data name="PinTab_PinTooltip" xml:space="preserve">
<value>釘選的標籤頁在重新登入後仍會保留,並持續綁定此對話對象。</value>
</data>
@@ -504,9 +486,9 @@
<value>已釘選,重新登入後仍會保留。</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Chat settings tab) -->
<data name="ChatLog_AutoTellTabs_Section_Title" xml:space="preserve">
<value>Auto-Tell-Tabs</value>
<value>自動悄悄話標籤頁</value>
</data>
<data name="ChatLog_AutoTellTabs_Enable_Name" xml:space="preserve">
<value>每收發一則 /tell 自動為對話對象開啟標籤頁</value>
@@ -515,7 +497,7 @@
<value>一旦收到或傳送 /tell,就會自動為該玩家開啟暫時標籤頁。登出時標籤頁將被移除。</value>
</data>
<data name="ChatLog_AutoTellTabs_Limit_Name" xml:space="preserve">
<value>Auto-Tell 標籤頁的最大數量</value>
<value>Auto-悄悄話 標籤頁的最大數量</value>
</data>
<data name="ChatLog_AutoTellTabs_Limit_Description" xml:space="preserve">
<value>達到上限時,活動最舊的已問候標籤頁會優先關閉。變更在下次 /tell 時生效。此限制僅適用於自動管理的標籤頁池。釘選的悄悄話標籤頁(右鍵 → 釘選標籤頁)存在於獨立的最多 5 個標籤頁池中,並在重新登入後保留。</value>
@@ -524,13 +506,13 @@
<value>緊湊顯示</value>
</data>
<data name="ChatLog_AutoTellTabs_Compact_Description" xml:space="preserve">
<value>在一般標籤頁和 Auto-Tell 標籤頁之間只顯示一條細分隔線,不顯示區段標題。</value>
<value>在一般標籤頁和 Auto-悄悄話 標籤頁之間只顯示一條細分隔線,不顯示區段標題。</value>
</data>
<data name="ChatLog_AutoTellTabs_GreetedToggle_Name" xml:space="preserve">
<value>顯示「標記為已問候」按鈕</value>
</data>
<data name="ChatLog_AutoTellTabs_GreetedToggle_Description" xml:space="preserve">
<value>在每個 Auto-Tell 標籤頁旁新增一個點擊按鈕,用於將對話對象標記為已問候,標籤頁名稱將隨之變暗。適合同時管理多個對話的接待人員使用。預設為關閉。</value>
<value>在每個 Auto-悄悄話 標籤頁旁新增一個點擊按鈕,用於將對話對象標記為已問候,標籤頁名稱將隨之變暗。適合同時管理多個對話的接待人員使用。預設為關閉。</value>
</data>
<data name="ChatLog_AutoTellTabs_OpenAsPopout_Name" xml:space="preserve">
<value>直接以彈出視窗開啟新的 /tell 標籤頁</value>
@@ -545,7 +527,7 @@
<value>注意:若 XIV Messenger 或類似插件抑制了悄悄話,請在該插件中停用「Suppress DMs」選項,使 Hellion Chat 能夠接收悄悄話並開啟自動標籤頁。</value>
</data>
<!-- Hellion Chat — Auto-Tell-Tabs (Privacy settings tab) -->
<data name="Privacy_AutoTellTabs_Section_Title" xml:space="preserve">
<value>自動標籤頁中的悄悄話歷史</value>
</data>
@@ -553,21 +535,15 @@
<value>預載悄悄話的數量</value>
</data>
<data name="Privacy_AutoTellTabs_Preload_Description" xml:space="preserve">
<value>開啟 Auto-Tell 標籤頁時從資料庫載入的先前悄悄話訊息數量。設為 0 則停用預載。</value>
<value>開啟 Auto-悄悄話 標籤頁時從資料庫載入的先前悄悄話訊息數量。設為 0 則停用預載。</value>
</data>
<data name="Privacy_AutoTellTabs_Preload_Hint" xml:space="preserve">
<value>只有在聊天標籤頁中啟用 Auto-Tell 標籤頁後才會生效。</value>
<value>只有在聊天標籤頁中啟用 Auto-悄悄話 標籤頁後才會生效。</value>
</data>
<!-- Hellion Chat — Settings UX Polish v10 Wipe migration -->
<data name="SettingsRefactor_Migration_Title" xml:space="preserve">
<value>設定已重新整理</value>
</data>
<data name="SettingsRefactor_Migration_Content" xml:space="preserve">
<value>Hellion Chat 0.5.0 已將設定重新整理為主題式標籤頁。你的聊天資料庫和訊息歷史保持不變。設定已重設為預設值。若要重新選擇隱私設定檔,請至隱私標籤頁中點擊重新開啟按鈕。先前設定的備份位於 HellionChat.json.pre-v10-backup,與目前使用中的設定檔位於同一目錄。</value>
</data>
<!-- Hellion Chat — Settings UX Polish 8-tab structure -->
<data name="Settings_Tab_General" xml:space="preserve">
<value>一般</value>
</data>
@@ -590,9 +566,9 @@
<value>關於</value>
</data>
<!-- Hellion Chat — General tab section headings -->
<!-- Hellion Chat — Appearance tab section headings -->
<data name="Settings_Appearance_Theme_Heading" xml:space="preserve">
<value>佈景主題</value>
</data>
@@ -606,14 +582,14 @@
<value>時間戳</value>
</data>
<!-- Hellion Chat — Window tab section headings -->
<data name="Settings_Window_Frame_Heading" xml:space="preserve">
<value>視窗框架</value>
</data>
<!-- Hellion Chat — Chat tab section headings -->
<!-- Hellion Chat — Chat tab SymbolPicker -->
<data name="Settings_Chat_SymbolPicker_Enable_Name" xml:space="preserve">
<value>在聊天輸入框旁顯示符號選擇器按鈕</value>
</data>
@@ -621,23 +597,17 @@
<value>在頻道指示器左側新增一個小按鈕,點擊後開啟含有 FFXIV 圖示和精選符號列表的彈出視窗。若偏好更簡潔的輸入列,可停用此選項。</value>
</data>
<!-- Hellion Chat — Database tab section headings -->
<data name="Settings_Database_Storage_Heading" xml:space="preserve">
<value>儲存</value>
</data>
<data name="Settings_Database_Viewer_Heading" xml:space="preserve">
<value>概覽</value>
</data>
<data name="Settings_Database_Stats_Heading" xml:space="preserve">
<value>維護</value>
</data>
<!-- Hellion Chat — Information tab section headings -->
<!-- Hellion Chat — Default tab presets (channel-specific) -->
<data name="Tabs_Presets_System" xml:space="preserve">
<value>系統</value>
</data>
<data name="Tabs_Presets_Emote" xml:space="preserve">
<value>情感動作</value>
</data>
<data name="Tabs_Presets_FreeCompany" xml:space="preserve">
<value>部隊</value>
</data>
@@ -654,7 +624,7 @@
<value>若你使用多個通訊貝,維護者建議每個通訊貝建立一個標籤頁以獲得更清晰的概覽。複製標籤頁,並在每個副本中限制頻道選擇。</value>
</data>
<!-- Hellion Chat — v1.2.0 per-tab icon override -->
<data name="Tabs_Icon_Label" xml:space="preserve">
<value>標籤頁圖示</value>
</data>
@@ -692,7 +662,7 @@
<value>啟用彈出視窗中的輸入功能</value>
</data>
<data name="Settings_Window_PopOutInputEnabled_Description" xml:space="preserve">
<value>主開關:允許在任何彈出視窗(包括 Auto-Tell 標籤頁)中直接輸入和傳送訊息。彈出視窗中的頻道切換會像主視窗一樣全域生效;文字緩衝區和歷史游標則各彈出視窗獨立。</value>
<value>主開關:允許在任何彈出視窗(包括 Auto-悄悄話 標籤頁)中直接輸入和傳送訊息。彈出視窗中的頻道切換會像主視窗一樣全域生效;文字緩衝區和歷史游標則各彈出視窗獨立。</value>
</data>
<data name="Settings_Window_ResetPosition_Name" xml:space="preserve">
<value>重設視窗位置</value>
@@ -700,24 +670,6 @@
<data name="Settings_Window_ResetPosition_Description" xml:space="preserve">
<value>將聊天視窗和所有已開啟的彈出視窗移回主螢幕左上角。適用於在顯示器配置變更後(螢幕斷線、解析度變更)視窗跑到可見區域外的情況。插件每次工作階段也會自動執行一次邊界檢查;若仍有視窗無法存取,此按鈕是手動應急出口。</value>
</data>
<data name="Popout_v060_HintText" xml:space="preserve">
<value>v0.6.0 新功能:現在可以直接在彈出視窗中輸入。請在視窗設定中啟用主開關。</value>
</data>
<data name="Popout_v060_HintAck" xml:space="preserve">
<value>了解</value>
</data>
<data name="Popout_v060_HintOpenSettings" xml:space="preserve">
<value>開啟視窗設定</value>
</data>
<data name="Hint_v061_PopOutHeader_Body" xml:space="preserve">
<value>你可以將任何聊天標籤頁以獨立視窗開啟。點擊右上角的視窗圖示,或右鍵點擊標籤頁。v0.6.1 新功能:彈出視窗輸入功能預設為啟用(可在設定 → 視窗中停用)。</value>
</data>
<data name="Hint_v061_PopOutHeader_Ack" xml:space="preserve">
<value>了解</value>
</data>
<data name="Hint_v061_PopOutHeader_OpenSettings" xml:space="preserve">
<value>開啟設定</value>
</data>
<data name="ChatTwoConflictTitle" xml:space="preserve">
<value>Hellion Chat 無法在 Chat 2 已載入的情況下啟動。</value>
</data>
@@ -727,54 +679,6 @@
<data name="ChatTwoConflictAction" xml:space="preserve">
<value>請在 /xlplugins 中停用 Chat 2,然後重新啟用 Hellion Chat。</value>
</data>
<data name="Settings_Card_General_Title" xml:space="preserve">
<value>一般</value>
</data>
<data name="Settings_Card_General_Subtext" xml:space="preserve">
<value>語言、輸入、音效和效能。</value>
</data>
<data name="Settings_Card_Appearance_Title" xml:space="preserve">
<value>外觀</value>
</data>
<data name="Settings_Card_Appearance_Subtext" xml:space="preserve">
<value>視窗不透明度、字型、動態效果</value>
</data>
<data name="Settings_Card_Themes_Title" xml:space="preserve">
<value>佈景主題</value>
</data>
<data name="Settings_Card_Themes_Subtext" xml:space="preserve">
<value>選擇佈景主題或匯入自訂主題</value>
</data>
<data name="Settings_Card_Window_Title" xml:space="preserve">
<value>視窗</value>
</data>
<data name="Settings_Card_Window_Subtext" xml:space="preserve">
<value>視窗的顯示時機以及是否可以移動。</value>
</data>
<data name="Settings_Card_Chat_Title" xml:space="preserve">
<value>聊天</value>
</data>
<data name="Settings_Card_Chat_Subtext" xml:space="preserve">
<value>悄悄話、預覽、訊息行為和情感動作。</value>
</data>
<data name="Settings_Card_Tabs_Title" xml:space="preserve">
<value>標籤頁</value>
</data>
<data name="Settings_Card_Tabs_Subtext" xml:space="preserve">
<value>建立和設定自訂聊天標籤頁。</value>
</data>
<data name="Settings_Card_Database_Title" xml:space="preserve">
<value>資料庫</value>
</data>
<data name="Settings_Card_Database_Subtext" xml:space="preserve">
<value>儲存、遷移、舊版清理</value>
</data>
<data name="Settings_Card_Information_Title" xml:space="preserve">
<value>關於</value>
</data>
<data name="Settings_Card_Information_Subtext" xml:space="preserve">
<value>擴充功能、版本、專案資訊、譯者和 Changelog。</value>
</data>
<data name="Settings_Tab_Themes" xml:space="preserve">
<value>佈景主題</value>
</data>
@@ -803,7 +707,7 @@
<value>保留</value>
</data>
<data name="StatusBar_Privacy_Enabled" xml:space="preserve">
<value>Privacy-First</value>
<value>隱私優先</value>
</data>
<data name="StatusBar_Privacy_Open" xml:space="preserve">
<value>開放</value>
@@ -817,9 +721,6 @@
<data name="Settings_Card_DataManagement_Title" xml:space="preserve">
<value>資料與隱私</value>
</data>
<data name="Settings_Card_DataManagement_Subtext" xml:space="preserve">
<value>隱私過濾器、保留、清理、匯出和資料庫統計資訊。</value>
</data>
<data name="Settings_ThemeAndLayout_Theme_Heading" xml:space="preserve">
<value>佈景主題</value>
</data>
@@ -838,9 +739,6 @@
<data name="Settings_DataManagement_Advanced_Heading" xml:space="preserve">
<value>進階(Shift+點擊開啟)</value>
</data>
<data name="Migration_v16_OverrideStyle_Toast" xml:space="preserve">
<value>Hellion Chat 1.2.1 已重新整理設定選單,並移除舊的「覆寫樣式」選項(已由 1.1.0 的佈景主題系統取代)。你其餘的設定保持不變。視窗透明度已遷移至「Theme &amp; Layout」。先前設定的備份位於 pluginConfigs/HellionChat.json.pre-v16-backup,與目前使用中的 HellionChat.json 位於同一目錄。</value>
</data>
<data name="Settings_Integrations_Intro" xml:space="preserve">
<value>插件整合功能讓 HellionChat 能與其他已安裝的 Dalamud 插件協同運作。每個整合功能會自動偵測目標插件,並在目標插件不存在時靜默停用自身。</value>
</data>
@@ -956,7 +854,7 @@
<comment>AI-assisted machine translation. Pending native-speaker review.</comment>
</data>
<!-- Hellion Chat — Settings Overhaul section titles (v1.5.6) -->
<data name="Settings_Section_Input" xml:space="preserve">
<value>輸入</value>
</data>
@@ -997,10 +895,7 @@
<value>輸入與預覽</value>
</data>
<data name="Settings_Section_AutoTellTabs" xml:space="preserve">
<value>自動Tell標籤頁</value>
</data>
<data name="Settings_Section_Emotes" xml:space="preserve">
<value>情感動作</value>
<value>自動悄悄話標籤頁</value>
</data>
<data name="Settings_Section_LinksTooltips" xml:space="preserve">
<value>連結與工具提示</value>
@@ -1146,4 +1041,324 @@
<data name="ChatInput_PluginDisclosure_Warning" xml:space="preserve">
<value>該訊息包含插件專用符號,其他玩家可能看到空白方框。再次按 Enter 鍵強制發送。</value>
</data>
</root>
<data name="InputBar_InsertSymbol_Tooltip" xml:space="preserve">
<value>插入符號</value>
</data>
<data name="InputBar_Settings_Tooltip" xml:space="preserve">
<value>設定</value>
</data>
<data name="InputBar_HideChat_Tooltip" xml:space="preserve">
<value>隱藏聊天(按 Enter 恢復)</value>
</data>
<data name="InputBar_PopIn_Tooltip" xml:space="preserve"><value>將此分頁移回主視窗</value>
</data>
<data name="Settings_Database_Busy" xml:space="preserve">
<value>另一項資料庫作業正在進行:{0}</value>
</data>
<data name="Settings_Database_Op_RetentionSweep" xml:space="preserve">
<value>保留期清理</value>
</data>
<data name="Settings_Database_Op_Export" xml:space="preserve">
<value>匯出</value>
</data>
<data name="Settings_Database_Op_Cleanup" xml:space="preserve">
<value>清理</value>
</data>
<data name="Settings_Database_Op_Clear" xml:space="preserve">
<value>清除歷史紀錄</value>
</data>
<data name="Cleanup_Unavailable_FilterOff" xml:space="preserve">
<value>隱私篩選器已關閉,因此所有頻道都會保存,資料庫中沒有與設定衝突的內容。請先開啟篩選器並選擇頻道。</value>
</data>
<data name="Cleanup_Unavailable_NothingListed" xml:space="preserve">
<value>未選擇任何頻道,因此清理會刪除全部歷史紀錄。請選擇要保留的頻道,若確實想全部刪除,請使用清除按鈕。</value>
</data>
<data name="Settings_Database_ClearHint" xml:space="preserve">
<value>已保存 {0:N0} 則訊息。若想留一份副本,請在清除前先匯出。</value>
</data>
<data name="Retention_RunNow_Tooltip" xml:space="preserve">
<value>Ctrl+Shift:立即執行保留期清理,無需等待每日執行。刪除早於上方期限的訊息。</value>
</data>
<data name="Settings_Database_ClearError" xml:space="preserve">
<value>清除歷史紀錄失敗。沒有刪除任何內容,請查看 /xllog。</value>
</data>
<data name="Settings_Section_Telemetry" xml:space="preserve">
<value>遙測</value>
</data>
<data name="Settings_Telemetry_None" xml:space="preserve">
<value>不收集任何遙測資料。外掛不會向任何地方傳送關於你或你使用情況的資訊。</value>
</data>
<data name="Settings_Section_AutoTranslate" xml:space="preserve">
<value>自動翻譯</value>
</data>
<data name="ChatLog_ScrollToBottom_Tooltip" xml:space="preserve">
<value>跳到最新訊息</value>
</data>
<data name="ChatLog_Insert_MapFlag" xml:space="preserve">
<value>插入地圖標記 &lt;flag&gt;</value>
</data>
<data name="ChatLog_Insert_ItemLink" xml:space="preserve">
<value>插入關聯物品 &lt;item&gt;</value>
</data>
<data name="Wizard_Step4_Summary_Off" xml:space="preserve">
<value>關閉</value>
</data>
<data name="Settings_Section_Behaviour" xml:space="preserve">
<value>行為</value>
</data>
<data name="Settings_Section_Keybinds" xml:space="preserve">
<value>快速鍵</value>
</data>
<data name="Settings_Section_Notifications" xml:space="preserve">
<value>通知</value>
</data>
<data name="Settings_Section_DisplayModes" xml:space="preserve">
<value>顯示模式</value>
</data>
<data name="Settings_Section_History" xml:space="preserve">
<value>歷史紀錄</value>
</data>
<data name="Settings_Section_CommandHelp" xml:space="preserve">
<value>指令說明</value>
</data>
<data name="Settings_Section_PluginDisclosure" xml:space="preserve">
<value>外掛提示</value>
</data>
<data name="Settings_Section_LayoutMode" xml:space="preserve">
<value>版面模式</value>
</data>
<data name="Settings_Section_Opacity" xml:space="preserve">
<value>不透明度</value>
</data>
<data name="Settings_Section_ResizeBehaviour" xml:space="preserve">
<value>調整大小行為</value>
</data>
<data name="Settings_Section_TellAutoOpen" xml:space="preserve">
<value>自動開啟悄悄話</value>
</data>
<data name="Settings_Section_Sidebar" xml:space="preserve">
<value>側邊欄</value>
</data>
<data name="Settings_Section_Brand" xml:space="preserve">
<value>品牌</value>
</data>
<data name="Settings_Section_Links" xml:space="preserve">
<value>連結</value>
</data>
<data name="Settings_Section_Integrations" xml:space="preserve">
<value>整合</value>
</data>
<data name="Settings_Section_Credits" xml:space="preserve">
<value>製作人員</value>
</data>
<data name="Settings_Section_License" xml:space="preserve">
<value>授權</value>
</data>
<data name="Settings_Keybinds_Hint" xml:space="preserve">
<value>點擊按鈕後按下組合鍵。Esc 清除。</value>
</data>
<data name="Settings_Keybinds_CycleNext" xml:space="preserve">
<value>切換到下一個分頁</value>
</data>
<data name="Settings_Keybinds_CyclePrevious" xml:space="preserve">
<value>切換到上一個分頁</value>
</data>
<data name="Settings_General_Language_Description" xml:space="preserve">
<value>切換會重建字型圖集,因此聊天會短暫空白。</value>
</data>
<data name="Settings_Chat_Clock24_Name" xml:space="preserve">
<value>24 小時制</value>
</data>
<data name="Settings_Chat_PreviousSessions_Name" xml:space="preserve">
<value>顯示先前工作階段的歷史紀錄</value>
</data>
<data name="Settings_Chat_PreviousSessions_Description" xml:space="preserve">
<value>關閉時,日誌在每次啟動遊戲時都是空的,只會填入此後收到的訊息。</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Name" xml:space="preserve">
<value>指令說明的位置</value>
</data>
<data name="Settings_Chat_CommandHelpSide_Description" xml:space="preserve">
<value>輸入時指令提示清單出現在哪一側。</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Name" xml:space="preserve">
<value>悄悄話自動開啟方式</value>
</data>
<data name="Settings_Channels_TellAutoOpenMode_Description" xml:space="preserve">
<value>悄悄話到達時在何處開啟。</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Name" xml:space="preserve">
<value>每則悄悄話都切換到分頁</value>
</data>
<data name="Settings_Channels_TellSwitchAlways_Description" xml:space="preserve">
<value>否則分頁會在第一則之後於背景開啟。</value>
</data>
<data name="Settings_Window_LayoutSidebar" xml:space="preserve">
<value>側邊欄</value>
</data>
<data name="Settings_Window_LayoutTopTabs" xml:space="preserve">
<value>頂部分頁</value>
</data>
<data name="Settings_Window_TabPlacement_Name" xml:space="preserve">
<value>分頁位置</value>
</data>
<data name="Settings_Window_TabPlacement_Description" xml:space="preserve">
<value>分頁清單在主視窗中的位置。</value>
</data>
<data name="Settings_Window_TitleBar_Name" xml:space="preserve">
<value>顯示標題列</value>
</data>
<data name="Settings_Window_PopoutTitleBar_Name" xml:space="preserve">
<value>顯示彈出視窗的標題列</value>
</data>
<data name="Settings_Window_AllowMove_Name" xml:space="preserve">
<value>允許移動</value>
</data>
<data name="Settings_Window_AllowResize_Name" xml:space="preserve">
<value>允許調整大小</value>
</data>
<data name="Settings_Window_SidebarThreshold_Name" xml:space="preserve">
<value>側邊欄自動切換閾值</value>
</data>
<data name="Settings_Window_SidebarThreshold_Description" xml:space="preserve">
<value>低於此寬度時側邊欄會摺疊為頂部分頁,單位為像素。</value>
</data>
<data name="Settings_Window_PreviewPosition_Name" xml:space="preserve">
<value>預覽位置</value>
</data>
<data name="Settings_Window_PreviewOnlyTyping_Name" xml:space="preserve">
<value>僅在輸入時顯示預覽</value>
</data>
<data name="Settings_About_GiteaRepo" xml:space="preserve">
<value>Gitea 儲存庫</value>
</data>
<data name="Settings_About_CustomRepo" xml:space="preserve">
<value>自訂儲存庫資訊清單</value>
</data>
<data name="Settings_Theme_ActiveTheme" xml:space="preserve">
<value>目前主題:{0}</value>
</data>
<data name="Settings_Theme_ForkAndEdit" xml:space="preserve">
<value>複製並編輯</value>
</data>
<data name="Settings_Theme_ForkTooltip" xml:space="preserve">
<value>內建主題無法直接編輯。複製會建立一份可編輯並儲存的自訂副本。</value>
</data>
<data name="Settings_Theme_EditTheme" xml:space="preserve">
<value>編輯主題</value>
</data>
<data name="Settings_Theme_Editing" xml:space="preserve">
<value>正在編輯:{0}</value>
</data>
<data name="Settings_Theme_Group_Surfaces" xml:space="preserve">
<value>表面</value>
</data>
<data name="Settings_Theme_Group_Borders" xml:space="preserve">
<value>邊框</value>
</data>
<data name="Settings_Theme_Group_Text" xml:space="preserve">
<value>文字</value>
</data>
<data name="Settings_Theme_Group_Identity" xml:space="preserve">
<value>身分</value>
</data>
<data name="Settings_Theme_Group_Status" xml:space="preserve">
<value>狀態</value>
</data>
<data name="Settings_Theme_Save" xml:space="preserve">
<value>儲存</value>
</data>
<data name="Settings_Theme_Cancel" xml:space="preserve">
<value>取消</value>
</data>
<data name="Settings_Theme_ResetToSource" xml:space="preserve">
<value>重設為原始主題</value>
</data>
<data name="Settings_Theme_ResetUnavailable" xml:space="preserve">
<value>編輯副本時無法重設。請先儲存或取消。</value>
</data>
<data name="Settings_Theme_LockedTooltip" xml:space="preserve">
<value>請先儲存或捨棄你的變更</value>
</data>
<data name="Settings_Theme_Custom" xml:space="preserve">
<value>自訂 ({0})</value>
</data>
<data name="Settings_Theme_ForkActive" xml:space="preserve">
<value>複製目前主題</value>
</data>
<data name="Settings_Theme_ImportFile" xml:space="preserve">
<value>匯入主題檔案…</value>
</data>
<data name="Settings_Theme_ImportPathHint" xml:space="preserve">
<value>JSON 檔案路徑(或拖放到資料夾)</value>
</data>
<data name="Settings_Theme_ExportDialogTitle" xml:space="preserve">
<value>匯出主題</value>
</data>
<data name="Settings_Theme_Category_Cool" xml:space="preserve">
<value>冷色</value>
</data>
<data name="Settings_Theme_Category_Natural" xml:space="preserve">
<value>自然</value>
</data>
<data name="Settings_Theme_Category_Classic" xml:space="preserve">
<value>經典</value>
</data>
<data name="Settings_Theme_Category_Retro" xml:space="preserve">
<value>復古</value>
</data>
<data name="Settings_Fonts_Bundled" xml:space="preserve">
<value>Hellion Inter(內建)</value>
</data>
<data name="Settings_Fonts_GameFont" xml:space="preserve">
<value>遊戲字型</value>
</data>
<data name="Settings_Fonts_Global" xml:space="preserve">
<value>全域:{0}</value>
</data>
<data name="Settings_Fonts_Active" xml:space="preserve">
<value>使用中:{0}</value>
</data>
<data name="Settings_Preview_TypeAMessage" xml:space="preserve">
<value>輸入訊息...</value>
</data>
<data name="Settings_Tabs_Duplicate" xml:space="preserve">
<value>複製</value>
</data>
<data name="Settings_Database_Op_Preview" xml:space="preserve">
<value>預覽</value>
</data>
<data name="Settings_Database_Op_Maintenance" xml:space="preserve">
<value>維護</value>
</data>
<data name="StatusBar_Tabs_One" xml:space="preserve">
<value>{0} 分頁</value>
</data>
<data name="StatusBar_Tabs_Other" xml:space="preserve">
<value>{0} 分頁</value>
</data>
<data name="StatusBar_Tells_One" xml:space="preserve">
<value>{0} 悄悄話</value>
</data>
<data name="StatusBar_Tells_Other" xml:space="preserve">
<value>{0} 悄悄話</value>
</data>
<data name="StatusBar_Messages" xml:space="preserve">
<value>{0} 則</value>
</data>
<data name="StatusBar_MessagesThousands" xml:space="preserve">
<value>{0:0.0}k 則</value>
</data>
<data name="Settings_Preview_TitleMock" xml:space="preserve">
<value>«冠軍» 預覽</value>
</data>
<data name="Settings_Preview_StatusOpen" xml:space="preserve">
<value>開啟</value>
</data>
<data name="ChannelHeader_NotLoggedIn" xml:space="preserve">
<value>未登入</value>
</data>
<data name="InputBar_More_Tooltip" xml:space="preserve">
<value>更多操作</value>
</data>
</root>
+2 -29
View File
@@ -527,10 +527,10 @@
<value>Finestra emergent</value>
</data>
<data name="Options_HideSameTimestamps_Name">
<value>Hide timestamps when redundant</value>
<value>Amaga les marques de temps redundants</value>
</data>
<data name="Options_HideSameTimestamps_Description">
<value>Hide timestamps when previous messages have the same timestamp.</value>
<value>Amaga la marca de temps quan el missatge anterior ja en té la mateixa.</value>
</data>
<data name="Options_ShowPopOutTitleBar_Name">
<value>Show title bar for popped-out tabs</value>
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Keeps the input focus, even if you enter battle or do other actions.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Show emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Replaces words with their emote version, currently supports BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blocked emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Hide during battle</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>Hide the chat during battles.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote Stats</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Ready</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Not Ready</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes available:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Displays a preview with special parameter evaluated, like emotes and &lt;item&gt;.</value>
</data>
-27
View File
@@ -1190,21 +1190,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Zachová fokus vstupu, i když vstoupíš do boje nebo provedeš jinou akci.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Zobrazit emoty</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Nahrazuje slova jejich emote verzí, aktuálně podporuje BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Zablokované emoty</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Skrýt v boji</value>
</data>
@@ -1217,18 +1202,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>Skryje chat, když je otevřeno menu New Game+. Zavřením menu se chat znovu zobrazí.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Statistiky emotů</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Připraveno</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Nepřipraveno</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Dostupné emoty:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Zobrazí náhled se speciálními parametry, jako jsou emoty a &lt;item&gt;.</value>
</data>
-27
View File
@@ -1190,21 +1190,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Beholder inputfokus, selvom du går i kamp eller udfører andre handlinger.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Vis emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Erstatter ord med deres emote-version, understøtter i øjeblikket BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blokerede emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Skjul under kamp</value>
</data>
@@ -1217,18 +1202,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>Skjuler chatten mens New Game+-menuen er åben. Lukning af menuen viser chatten igen.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote-statistik</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Klar</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Ikke klar</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Tilgængelige emotes:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Viser en forhåndsvisning med særlige parametre evalueret, som emotes og &lt;item&gt;.</value>
</data>
-27
View File
@@ -1189,21 +1189,6 @@ Sie wurden gewarnt.</value>
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Der Eingabefokus wird beibehalten, selbst wenn du einen Kampf betrittst oder eine andere Aktion ausführst.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Emotes anzeigen</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Ersetzt Wörter mit ihrer Emote-Version, unterstützt derzeit BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blockierte Emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Während des Kampfes ausblenden</value>
</data>
@@ -1216,18 +1201,6 @@ Sie wurden gewarnt.</value>
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>Blendet den Chat aus, solange das New-Game+ Menü geöffnet ist. Schließen des Menüs blendet den Chat wieder ein.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote-Statistik</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Bereit</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Nicht bereit</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes verfügbar:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Zeigt eine Vorschau mit speziellen Parametern, wie Emotes und &lt;item&gt;.</value>
</data>
-27
View File
@@ -1190,21 +1190,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Διατηρεί την εστίαση εισαγωγής, ακόμα και αν μπεις σε μάχη ή κάνεις άλλες ενέργειες.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Εμφάνιση emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Αντικαθιστά λέξεις με την έκδοση emote τους, υποστηρίζει αυτή τη στιγμή BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Αποκλεισμένα emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Απόκρυψη κατά τη μάχη</value>
</data>
@@ -1217,18 +1202,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>Απόκρυψη της συνομιλίας ενώ το μενού New Game+ είναι ανοιχτό. Το κλείσιμο του μενού εμφανίζει ξανά τη συνομιλία.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Στατιστικά Emote</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Έτοιμο</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Μη έτοιμο</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Διαθέσιμα emotes:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Εμφανίζει προεπισκόπηση με αξιολόγηση ειδικών παραμέτρων, όπως emotes και &lt;item&gt;.</value>
</data>
+1 -28
View File
@@ -731,7 +731,7 @@
<value>Decir</value>
</data>
<data name="ChatType_Shout">
<value>Shout</value>
<value>Vociferar</value>
</data>
<data name="ChatType_TellOutgoing">
<value>Tell (saliente)</value>
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Mantiene el foco de entrada, incluso si entras en combate o realizas otras acciones.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Mostrar emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Reemplaza las palabras por su versión de emote, actualmente soporta BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Gestos</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Emotes bloqueados</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Gesto</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Ocultar durante el combate</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>Ocultar el chat durante combates.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Estadísticas de gestos</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Listo</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>No listo</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Gestos disponibles:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Muestra una vista previa con un parámetro especial evaluado, como emotes o &lt;item&gt;.</value>
</data>
-27
View File
@@ -1190,21 +1190,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Pitää syöttöfokuksen, vaikka siirtyisit taisteluun tai tekisit muita toimintoja.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Näytä emootiot</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Korvaa sanat niiden emootioversioilla, tukee tällä hetkellä BetterTTV:tä.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emootiot</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Estetyt emootiot</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emootio</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Piilota taistelun aikana</value>
</data>
@@ -1217,18 +1202,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>Piilottaa chatin New Game+ -valikon ollessa auki. Sulkeminen näyttää chatin uudelleen.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emootiotilastot</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Valmis</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Ei valmis</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emootioita saatavilla:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Näyttää esikatselun erikoisparametreilla arvioituna, kuten emootiot ja &lt;item&gt;.</value>
</data>
-27
View File
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Maintient le focus de saisie, même si vous entrez au combat ou faites d'autres actions.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Afficher les emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Remplace les mots par leur version emote, prend actuellement en charge BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Émotes bloquées</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Cacher pendant le combat</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>Cacher le chat pendant les combats.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Statistiques de l'emote</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Prêt</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Pas prêt</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes disponibles :</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Affiche un aperçu avec un paramètre spécial estimé, comme les emotes et &lt;item&gt;.</value>
</data>
-27
View File
@@ -1190,21 +1190,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Megtartja a beviteli fókuszt, még harc közben vagy más műveletek végzésekor is.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Emote-ok megjelenítése</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Szavakat helyettesít az emote változatukkal, jelenleg a BetterTTV-t támogatja.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emote-ok</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blokkolt emote-ok</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Elrejtés harc közben</value>
</data>
@@ -1217,18 +1202,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>A chat elrejtése, amíg a New Game+ menü nyitva van. A menü bezárásakor a chat újra megjelenik.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote statisztikák</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Kész</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Nem kész</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Elérhető emote-ok:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Előnézetet jelenít meg kiértékelt speciális paraméterekkel, például emote-ok és &lt;item&gt;.</value>
</data>
+2 -29
View File
@@ -527,10 +527,10 @@
<value>Pop out</value>
</data>
<data name="Options_HideSameTimestamps_Name">
<value>Hide timestamps when redundant</value>
<value>Nascondi gli orari ridondanti</value>
</data>
<data name="Options_HideSameTimestamps_Description">
<value>Hide timestamps when previous messages have the same timestamp.</value>
<value>Nasconde l'orario quando il messaggio precedente ha già lo stesso.</value>
</data>
<data name="Options_ShowPopOutTitleBar_Name">
<value>Show title bar for popped-out tabs</value>
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Keeps the input focus, even if you enter battle or do other actions.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Show emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Replaces words with their emote version, currently supports BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blocked emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Nascondi in battaglia</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>Nascondi la chat in battaglia.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote Stats</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Pronto</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Non pronto</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes available:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Displays a preview with special parameter evaluated, like emotes and &lt;item&gt;.</value>
</data>
-27
View File
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>戦闘に入ったり、他のアクションを行ったりしても、入力フォーカスを維持します。</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>エモートを表示</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>単語をエモートバージョンに置き換え、現在BetterTTVをサポートしています。</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>エモート</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>ブロックされたエモート</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>エモート</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>戦闘中は非表示</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>戦闘中はチャットを非表示にします。</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote Stats</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>準備完了</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>未準備</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>利用可能なエモート:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>emotes や &lt;item&gt; のように、特別なパラメータが評価されたプレビューを表示します。</value>
</data>
-27
View File
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Keeps the input focus, even if you enter battle or do other actions.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Show emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Replaces words with their emote version, currently supports BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blocked emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Hide during battle</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>Hide the chat during battles.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote Stats</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Ready</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Not Ready</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes available:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Displays a preview with special parameter evaluated, like emotes and &lt;item&gt;.</value>
</data>
-27
View File
@@ -1190,21 +1190,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Beholder inndatafokuset selv om du går inn i kamp eller gjør andre handlinger.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Vis emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Erstatter ord med tilsvarende emote-versjon. Støtter for øyeblikket BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blokkerte emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Skjul under kamp</value>
</data>
@@ -1217,18 +1202,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>Skjuler chatten mens New Game+-menyen er åpen. Chatten vises igjen når menyen lukkes.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote-statistikk</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Klar</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Ikke klar</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Tilgjengelige emotes:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Viser en forhåndsvisning med spesielle parametere evaluert, som emotes og &lt;item&gt;.</value>
</data>
-27
View File
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Houdt de invoerfocus vast, zelfs als je een gevecht aangaat of andere acties uitvoert.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Emotes tonen</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Vervangt woorden door hun emote-versie, ondersteunt momenteel BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Geblokkeerde emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Verbergen tijdens gevecht</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>Verberg de chat tijdens gevechten.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote-statistieken</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Gereed</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Niet Gereed</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes beschikbaar:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Toont een voorvertoning met geëvalueerde speciale parameters, zoals emotes en &lt;item&gt;.</value>
</data>
-27
View File
@@ -1190,21 +1190,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Utrzymuje fokus na polu wprowadzania, nawet jeśli wejdziesz w walkę lub wykonasz inne czynności.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Pokaż emoty</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Zastępuje słowa ich wersją emotów, obecnie obsługuje BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emoty</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Zablokowane emoty</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emot</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Ukryj podczas walki</value>
</data>
@@ -1217,18 +1202,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>Ukrywa czat gdy menu New Game+ jest otwarte. Zamknięcie menu pokazuje czat z powrotem.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Statystyki emotów</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Gotowe</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Niegotowe</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Dostępne emoty:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Wyświetla podgląd z obliczonymi parametrami specjalnymi, jak emoty i &lt;item&gt;.</value>
</data>
-27
View File
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Mantém o foco de entrada, mesmo que você entre em batalha ou faça outras ações.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Exibir gestos</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Substitui as palavras por sua versão de gesto, atualmente suporta BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Gesto</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Gestos bloqueados</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Gesto</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Esconder durante combate</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>Esconder o bate-papo durante combate.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Status de Gestos</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Pronto</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Não está pronto</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Gestos disponíveis:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Exibe uma prévia com parâmetro especial avaliado, como gestos e &lt;item&gt;.</value>
</data>
-27
View File
@@ -1190,21 +1190,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Mantém o foco no campo de entrada mesmo que entres em combate ou faças outras ações.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Mostrar emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Substitui palavras pela versão em emote correspondente. Suporta atualmente o BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Emotes bloqueados</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Ocultar durante o combate</value>
</data>
@@ -1217,18 +1202,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>Oculta o chat enquanto o menu New Game+ está aberto. Ao fechar o menu, o chat volta a ser apresentado.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Estatísticas de emotes</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Pronto</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Não está pronto</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes disponíveis:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Apresenta uma pré-visualização com parâmetros especiais avaliados, como emotes e &lt;item&gt;.</value>
</data>
-27
View File
@@ -1174,21 +1174,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Keeps the input focus, even if you enter battle or do other actions.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Show emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Replaces words with their emote version, currently supports BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blocked emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Hide during battle</value>
</data>
@@ -1201,18 +1186,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>Hide the chat while the New Game+ menu is open. Closing the menu shows the chat again.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote Stats</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Ready</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Not Ready</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes available:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Displays a preview with special parameter evaluated, like emotes and &lt;item&gt;.</value>
</data>
-27
View File
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Keeps the input focus, even if you enter battle or do other actions.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Show emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Replaces words with their emote version, currently supports BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blocked emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Hide during battle</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>Hide the chat during battles.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote Stats</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Ready</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Not Ready</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes available:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Displays a preview with special parameter evaluated, like emotes and &lt;item&gt;.</value>
</data>
-27
View File
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Keeps the input focus, even if you enter battle or do other actions.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Show emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Replaces words with their emote version, currently supports BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blocked emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Hide during battle</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>Hide the chat during battles.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote Stats</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Ready</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Not Ready</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes available:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Displays a preview with special parameter evaluated, like emotes and &lt;item&gt;.</value>
</data>
-27
View File
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Keeps the input focus, even if you enter battle or do other actions.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Show emotes</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Replaces words with their emote version, currently supports BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emotes</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Blocked emotes</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Hide during battle</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>Hide the chat during battles.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote Stats</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Ready</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Not Ready</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Emotes available:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Displays a preview with special parameter evaluated, like emotes and &lt;item&gt;.</value>
</data>
-27
View File
@@ -1190,21 +1190,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Savaşa girerken veya başka eylemler yaparken bile giriş odağını korur.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Emote'ları göster</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Kelimeleri emote sürümleriyle değiştirir, şu an BetterTTV desteklenmektedir.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Emote'lar</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Engellenen emote'lar</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Emote</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Savaş sırasında gizle</value>
</data>
@@ -1217,18 +1202,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>New Game+ menüsü açıkken sohbeti gizler. Menüyü kapatmak sohbeti tekrar gösterir.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Emote İstatistikleri</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Hazır</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Hazır Değil</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Kullanılabilir emote'lar:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Emote'lar ve &lt;item&gt; gibi özel parametrelerin değerlendirildiği bir önizleme gösterir.</value>
</data>
-27
View File
@@ -1190,21 +1190,6 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>Зберігає фокус введення навіть під час бою чи інших дій.</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>Показувати емоти</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>Замінює слова їх версіями емотів. Наразі підтримує BetterTTV.</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>Емоти</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>Заблоковані емоти</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>Емот</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>Приховувати під час бою</value>
</data>
@@ -1217,18 +1202,6 @@
<data name="Options_HideInNewGamePlusMenu_Description" xml:space="preserve">
<value>Приховати чат, поки відкрито меню New Game+. Закриття меню знову показує чат.</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>Статистика емотів</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>Готово</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>Не готово</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>Доступно емотів:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>Показує попередній перегляд з обробленими спеціальними параметрами, як-от емоти та &lt;item&gt;.</value>
</data>
-27
View File
@@ -1168,39 +1168,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>保持输入焦点,即使你进入战斗或执行其他操作。</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>显示表情</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>用表情替换单词,目前支持 BetterTTV。</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>表情</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>已屏蔽的表情</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>表情</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>在战斗中隐藏</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>在战斗中隐藏聊天窗</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>表情状态</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>准备就绪</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>尚未准备好</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>可用表情: </value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>显示特殊参数预览,如表情和 &lt;item&gt;。</value>
</data>
-27
View File
@@ -1169,39 +1169,12 @@
<data name="Options_KeepInputFocus_Description" xml:space="preserve">
<value>保持輸入焦點,即使進入戰鬥或執行其他操作。</value>
</data>
<data name="Options_ShowEmotes_Name" xml:space="preserve">
<value>顯示表情</value>
</data>
<data name="Options_ShowEmotes_Desc" xml:space="preserve">
<value>用表情替換單詞,目前支持 BetterTTV。</value>
</data>
<data name="Options_Emote_Tab" xml:space="preserve">
<value>表情</value>
</data>
<data name="Options_Emote_BlockedEmotes" xml:space="preserve">
<value>已屏蔽的表情</value>
</data>
<data name="Options_Emote_EmoteTable" xml:space="preserve">
<value>表情</value>
</data>
<data name="Options_HideInBattle_Name" xml:space="preserve">
<value>在戰鬥中隱藏</value>
</data>
<data name="Options_HideInBattle_Description" xml:space="preserve">
<value>在戰鬥中隱藏聊天窗。</value>
</data>
<data name="Options_Emote_EmoteStats" xml:space="preserve">
<value>表情狀態</value>
</data>
<data name="Options_Emote_Ready" xml:space="preserve">
<value>已就緒</value>
</data>
<data name="Options_Emote_NotReady" xml:space="preserve">
<value>尚未就緒</value>
</data>
<data name="Options_Emote_Loaded" xml:space="preserve">
<value>可用表情:</value>
</data>
<data name="Options_Preview_Description" xml:space="preserve">
<value>顯示特殊參數預覽,如表情或 &lt;item&gt;。</value>
</data>
@@ -0,0 +1,101 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
using HellionChat.Integrations;
namespace HellionChat.SelfTests;
// Verifies the About-tab integrations status. The pure HonorificStatus.Resolve
// covers the three-state mapping (false-green-free); driving the real AboutTab
// render once proves the render path actually calls the resolver (sets
// LastHonorificStatusKey). Set -> Draw -> Assert happen in ONE synchronous
// RunStep so a between-frame Honorific IPC callback can't clobber the seam
// state; the prior service state is restored in CleanUp.
internal sealed class AboutIntegrationsStatusStep : ISelfTestStep
{
private readonly Plugin plugin;
private HonorificService? _svc;
private bool _prevAvailable;
private (uint Major, uint Minor)? _prevVersion;
private HonorificTitleData? _prevTitle;
private bool _snapshotted;
public AboutIntegrationsStatusStep(Plugin plugin)
{
this.plugin = plugin;
}
public string Name => "Hellion Chat - About integrations status";
public SelfTestStepResult RunStep()
{
// AboutTab.Draw renders DrawBrand/coming-soon under _fonts.FontAwesome.Push;
// wait until the atlas is built so the render can't misbehave. Returned
// BEFORE any snapshot/Set, so no seam state leaks (same guard as the header
// step; precedent FoxBannerTextureSmokeStep).
if (!plugin.FontManager.FontsReady)
{
return SelfTestStepResult.Waiting;
}
// Pure mapping (incl. the isAvailable=true + null boundary -> NotInstalled).
if (
HonorificStatus.Resolve(true, (3, 1)) != HonorificStatusKind.Detected
|| HonorificStatus.Resolve(false, (2, 5)) != HonorificStatusKind.Incompatible
|| HonorificStatus.Resolve(false, null) != HonorificStatusKind.NotInstalled
|| HonorificStatus.Resolve(true, null) != HonorificStatusKind.NotInstalled
)
{
ImGui.Text("HonorificStatus.Resolve mapping is wrong");
return SelfTestStepResult.Fail;
}
var about = plugin.SettingsWindow.GetAboutTabForSelfTest();
if (about is null)
{
ImGui.Text("SettingsWindow.AboutTab reference is null");
return SelfTestStepResult.Fail;
}
_svc = plugin.MainWindow.GetHonorificHeaderForSelfTest()?.GetServiceForSelfTest();
if (_svc is null)
{
ImGui.Text("HonorificService reference is null");
return SelfTestStepResult.Fail;
}
_prevAvailable = _svc.IsAvailable;
_prevVersion = _svc.DetectedApiVersion;
_prevTitle = _svc.CurrentTitle;
_snapshotted = true;
try
{
// Drive the real render once and confirm the resolver is wired in.
_svc.TestOnly_SetState(true, (3, 1), null);
about.Draw();
if (about.LastHonorificStatusKey != HonorificStatusKind.Detected.ToString())
{
ImGui.Text(
$"About render did not resolve Detected (got {about.LastHonorificStatusKey})"
);
return SelfTestStepResult.Fail;
}
}
catch (Exception ex)
{
ImGui.Text($"AboutTab.Draw threw: {ex.GetType().Name}: {ex.Message}");
return SelfTestStepResult.Fail;
}
return SelfTestStepResult.Pass;
}
public void CleanUp()
{
if (!_snapshotted || _svc is null)
return;
_svc.TestOnly_SetState(_prevAvailable, _prevVersion, _prevTitle);
_snapshotted = false;
}
}
+111
View File
@@ -0,0 +1,111 @@
using System.Collections.Generic;
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
using HellionChat.Util;
namespace HellionChat.SelfTests;
// Behavioural check that the card path feeds CardClipPlanner AND that a
// layout change clears the height cache — not a non-null check. Pure plan math
// is pinned headless by CardClipPlanTests; this drives the live accessors.
internal sealed class CardClipPlanStep : ISelfTestStep
{
private readonly Plugin plugin;
public CardClipPlanStep(Plugin plugin) => this.plugin = plugin;
public string Name => "Hellion Chat - Card clip plan + cache invalidation";
public SelfTestStepResult RunStep()
{
var messages = plugin.MainWindow.GetMessageListForSelfTest();
if (messages is null)
{
ImGui.Text("MessageList null");
SelfTestReport.Append(Name, "FAIL", new[] { "MessageList null" });
return SelfTestStepResult.Fail;
}
// 5 rows of 20, viewport 50, scroll 45 -> skip rows 0,1 (lead 40), see 2..4.
IReadOnlyList<float> heights = [20f, 20f, 20f, 20f, 20f];
var plan = messages.PlanCardClipForSelfTest(heights, scrollY: 45f, viewportHeight: 50f);
if (
plan.FirstVisible != 2
|| plan.LastVisible != 4
|| plan.LeadDummyHeight is < 39.9f or > 40.1f
)
{
var msg =
$"Plan wrong: first={plan.FirstVisible} last={plan.LastVisible} lead={plan.LeadDummyHeight}";
ImGui.Text(msg);
SelfTestReport.Append(Name, "FAIL", new[] { msg });
return SelfTestStepResult.Fail;
}
var tab = plugin.MainWindow.ActiveTab;
if (tab is null)
{
ImGui.Text("No active tab");
SelfTestReport.Append(Name, "FAIL", new[] { "No active tab" });
return SelfTestStepResult.Fail;
}
// Flip a height-affecting mode -> fingerprint changes -> cache must drop.
// Config restored in finally (live-singleton discipline).
var savedForm = Plugin.Config.NameFormMode;
int remaining;
try
{
// v1.10.0: the fingerprint gate waits for the value to settle, so
// the step walks a synthetic clock past the window instead of sleeping.
var clock = Environment.TickCount64;
messages.RunHeightCacheInvalidationForSelfTest(tab, 400f, clock);
using (var snap = tab.Messages.GetReadOnly(3))
{
if (snap.Count > 0)
snap[0].Height[tab.Identifier] = 42f;
}
Plugin.Config.NameFormMode =
savedForm == NameFormMode.Full ? NameFormMode.Initials : NameFormMode.Full;
messages.RunHeightCacheInvalidationForSelfTest(tab, 400f, clock);
clock += LayoutFingerprintGate.SettleMs;
remaining = messages.RunHeightCacheInvalidationForSelfTest(tab, 400f, clock);
}
finally
{
Plugin.Config.NameFormMode = savedForm;
var restore = Environment.TickCount64 + LayoutFingerprintGate.SettleMs * 2;
messages.RunHeightCacheInvalidationForSelfTest(tab, 400f, restore);
messages.RunHeightCacheInvalidationForSelfTest(
tab,
400f,
restore + LayoutFingerprintGate.SettleMs
);
}
if (remaining != 0)
{
var msg = $"Cache not cleared after layout change: {remaining} left";
ImGui.Text(msg);
SelfTestReport.Append(Name, "FAIL", new[] { msg });
return SelfTestStepResult.Fail;
}
SelfTestReport.Append(
Name,
"PASS",
new[]
{
$"Plan range [{plan.FirstVisible}..{plan.LastVisible}], lead={plan.LeadDummyHeight}",
"Height cache cleared after layout-fingerprint change",
}
);
ImGui.Text(
$"PASS — plan [{plan.FirstVisible}..{plan.LastVisible}], cache cleared on layout change."
);
return SelfTestStepResult.Pass;
}
public void CleanUp() { }
}
@@ -0,0 +1,115 @@
using System.Linq;
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
namespace HellionChat.SelfTests;
// In-game behavioural check of the ChannelPopoutPool lifecycle (not a non-null-handle
// check — feedback_hellion_chat_fontmanager_push_trap): pre-alloc count, unique slot
// ids, a TryOpen->IsOpen->TryClose round-trip, idempotent close, and capacity refusal.
// The pool is a live DI singleton, so the step works against the FREE slots (not full
// capacity) and only closes ids it opened — it neither false-REDs on a non-empty pool
// nor disturbs real pop-outs. Pure slot-map math is pinned by PopoutSlotMapTests.
internal sealed class ChannelPopoutBindStep : ISelfTestStep
{
private readonly Plugin _plugin;
public ChannelPopoutBindStep(Plugin plugin)
{
_plugin = plugin;
}
public string Name => "Hellion Chat - Channel popout pool lifecycle";
public SelfTestStepResult RunStep()
{
var pool = _plugin.ChannelPopoutPool;
var capacity = Plugin.Config.MaxParallelPopouts;
if (pool.Instances.Count != capacity)
{
ImGui.Text(
$"Expected {capacity} pre-allocated pop-out windows, found {pool.Instances.Count}."
);
return SelfTestStepResult.Fail;
}
if (pool.Instances.Select(w => w.SlotIndex).Distinct().Count() != pool.Instances.Count)
{
ImGui.Text("Pop-out windows do not have unique slot indices.");
return SelfTestStepResult.Fail;
}
// Free slots right now = capacity minus whatever real pop-outs are already
// bound. Testing against this (not capacity) keeps the step state-independent.
var free = capacity - pool.Instances.Count(w => w.Bound is not null);
// Round-trip on a throwaway tab, only when there's a slot to take. A bare Tab
// has CurrentChannel.Channel == Invalid + an empty SelectedChannels, so the
// pool's OnTabActivated strip is a no-op (no NRE), and the live active tab is
// passed only as `previous`, so it is never mutated. We close before
// returning, so the bound window never reaches a Draw frame.
if (free > 0)
{
var probe = new Tab { Name = "##selftest-popout-probe" };
if (pool.IsOpen(probe.Identifier))
{
ImGui.Text("Probe tab already open before TryOpen.");
return SelfTestStepResult.Fail;
}
if (!pool.TryOpen(probe))
{
ImGui.Text("TryOpen returned false with a free slot.");
return SelfTestStepResult.Fail;
}
if (!pool.IsOpen(probe.Identifier))
{
ImGui.Text("IsOpen is false right after a successful TryOpen.");
pool.TryClose(probe.Identifier);
return SelfTestStepResult.Fail;
}
pool.TryClose(probe.Identifier);
if (pool.IsOpen(probe.Identifier))
{
ImGui.Text("IsOpen is still true after TryClose.");
return SelfTestStepResult.Fail;
}
// Idempotent: closing an already-closed id is a silent no-op.
pool.TryClose(probe.Identifier);
}
// Capacity guard: fill the remaining free slots, then one more open must be
// refused (warn, no throw). Release everything we opened before reporting.
var fillers = Enumerable
.Range(0, free)
.Select(_ => new Tab { Name = "##selftest-fill" })
.ToList();
var opened = fillers.Count(pool.TryOpen);
var overflow = new Tab { Name = "##selftest-overflow" };
var overflowRejected = !pool.TryOpen(overflow);
foreach (var filler in fillers)
pool.TryClose(filler.Identifier);
pool.TryClose(overflow.Identifier);
if (opened != free)
{
ImGui.Text($"Filled only {opened}/{free} free slots before TryOpen refused.");
return SelfTestStepResult.Fail;
}
if (!overflowRejected)
{
ImGui.Text("Pool accepted an open beyond capacity instead of refusing.");
return SelfTestStepResult.Fail;
}
return SelfTestStepResult.Pass;
}
public void CleanUp() { }
}
@@ -0,0 +1,37 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
namespace HellionChat.SelfTests;
// ChunkRenderer is a plain singleton (PluginHostFactory.cs:247) consumed by the
// real render path (MainWindow/MessageList/InputPreview DrawChunks). One
// resolution path is enough — unlike PayloadHandler there is no Lender. The
// type exposes no post-ctor observables (no LoadException-style state), so the
// honest assertion is "the DI ctor resolved a non-null instance". If a
// dependency registration breaks, Plugin's eager resolve throws before this
// step; the step pins that the singleton is reachable through the real
// container property, not via new().
internal sealed class ChunkRendererCtorSmokeStep : ISelfTestStep
{
private readonly Plugin plugin;
public ChunkRendererCtorSmokeStep(Plugin plugin)
{
this.plugin = plugin;
}
public string Name => "Hellion Chat - ChunkRenderer ctor smoke";
public SelfTestStepResult RunStep()
{
if (this.plugin.ChunkRenderer is null)
{
ImGui.Text("Plugin.ChunkRenderer is null");
return SelfTestStepResult.Fail;
}
return SelfTestStepResult.Pass;
}
public void CleanUp() { }
}
@@ -0,0 +1,68 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
using HellionChat.Themes;
namespace HellionChat.SelfTests;
internal sealed class ColorEditorBufferStep : ISelfTestStep
{
private readonly Plugin _plugin;
public ColorEditorBufferStep(Plugin plugin)
{
_plugin = plugin;
}
public string Name => "Hellion Chat - Color editor buffer";
public SelfTestStepResult RunStep()
{
var registry = _plugin.ThemeRegistry;
var originalActive = registry.Active;
var fired = 0;
Action handler = () => fired++;
try
{
registry.OnEditingBufferChanged += handler;
registry.BeginEditing(originalActive);
if (registry.EditingThemeBuffer is null)
{
ImGui.Text("EditingThemeBuffer should not be null after BeginEditing");
return SelfTestStepResult.Fail;
}
var mutatedColors = registry.EditingThemeBuffer.Colors with { Primary = 0xFF112233 };
registry.UpdateEditingBuffer(mutatedColors);
if (fired != 1)
{
ImGui.Text($"Expected OnEditingBufferChanged once, got {fired}");
return SelfTestStepResult.Fail;
}
registry.DiscardEditingBuffer();
if (registry.EditingThemeBuffer is not null)
{
ImGui.Text("EditingThemeBuffer should be null after Discard");
return SelfTestStepResult.Fail;
}
if (registry.Active != originalActive)
{
ImGui.Text("Active theme should be unchanged after Discard");
return SelfTestStepResult.Fail;
}
return SelfTestStepResult.Pass;
}
finally
{
registry.OnEditingBufferChanged -= handler;
}
}
public void CleanUp() { }
}
@@ -0,0 +1,114 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
namespace HellionChat.SelfTests;
// Pins the post-migration shape of the config. By /xlperf time the schema gate
// has stamped Config.Version and the 2.0.0 reset has run, so the fields below
// must carry valid values here. This probe never rewrites config; the reset
// itself is load-time.
internal sealed class ConfigMigrationV27Step : ISelfTestStep
{
public ConfigMigrationV27Step(Plugin plugin)
{
_ = plugin;
}
public string Name => "Hellion Chat - Config v27 migration";
public SelfTestStepResult RunStep()
{
if (Plugin.Config.Version != 27)
{
ImGui.Text($"Config.Version is {Plugin.Config.Version}, expected 27");
return SelfTestStepResult.Fail;
}
// v27 replaces the config rather than migrating it, and CreateFresh
// hands back an empty tab list. The seeding in LoadAsync is what fills
// it, and it runs in a different method than the reset does -- if that
// ordering ever breaks, every user comes out of the update with no tabs
// at all and nothing else in the plugin would notice.
if (Plugin.Config.Tabs.Count == 0)
{
ImGui.Text(
"No tabs at all. The v27 reset empties the list and LoadAsync is what "
+ "seeds the presets back -- reaching this point empty means it did not."
);
return SelfTestStepResult.Fail;
}
// What v26 exists to prevent: a tab whose name came from a conversation
// partner but is not marked as such, because screenshot mode reads that
// mark to decide whether the name may be shown. Anything still holding a
// tell binding or the temp flag should have been marked on load.
foreach (var tab in Plugin.Config.Tabs)
{
var looksLikeAPartner = tab.IsTempTab || tab.TellTarget?.IsSet() == true;
if (!looksLikeAPartner || tab.NameCameFromPartner)
continue;
ImGui.Text(
$"Tab '{tab.Name}' carries a tell binding but is not marked partner-named "
+ "— the v26 migration did not reach it, and screenshot mode will show it"
);
return SelfTestStepResult.Fail;
}
// The state the v24 migration exists to prevent: filter on, failsafe on,
// nothing picked. Under the corrected rule that combination stores no
// messages at all, so reaching /xlperf in it means the migration did not
// run.
if (
Privacy.StorageRule.ShouldDisableFilterOnV24(
Plugin.Config.PrivacyFilterEnabled,
Plugin.Config.PrivacyPersistUnknownChannels,
Plugin.Config.PrivacyPersistChannels.Count
)
)
{
ImGui.Text("Privacy filter is on with no channels picked — v24 migration did not run");
return SelfTestStepResult.Fail;
}
if (Plugin.Config.MaxParallelPopouts <= 0)
{
ImGui.Text(
$"Config.MaxParallelPopouts is {Plugin.Config.MaxParallelPopouts}, must be > 0"
);
return SelfTestStepResult.Fail;
}
if (Plugin.Config.SidebarAutoSwitchThresholdPx <= 0)
{
ImGui.Text(
$"Config.SidebarAutoSwitchThresholdPx is {Plugin.Config.SidebarAutoSwitchThresholdPx}, must be > 0"
);
return SelfTestStepResult.Fail;
}
if (!Enum.IsDefined(Plugin.Config.TellAutoOpenMode))
{
ImGui.Text($"Config.TellAutoOpenMode {Plugin.Config.TellAutoOpenMode} is out of range");
return SelfTestStepResult.Fail;
}
if (!Enum.IsDefined(Plugin.Config.MainWindowLayoutMode))
{
ImGui.Text(
$"Config.MainWindowLayoutMode {Plugin.Config.MainWindowLayoutMode} is out of range"
);
return SelfTestStepResult.Fail;
}
// Touch-tests: declaration proves the migration emitted these with
// defaults; reading them confirms the property is reachable.
_ = Plugin.Config.MainWindowOpen;
_ = Plugin.Config.SettingsWindowOpen;
_ = Plugin.Config.ScreenshotMode;
return SelfTestStepResult.Pass;
}
public void CleanUp() { }
}
@@ -0,0 +1,125 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
namespace HellionChat.SelfTests;
// CurrentTab is coupled to MainWindow.ActiveTab (no longer the fixed index-0
// Tabs lookup). Asserts ReferenceEquals between the two, with false-green
// defenses: (1) empty-config exercises the getter's fallback; (2) null ActiveTab
// opens the window so the Draw-seed sets it and retries via Waiting (bounded so a
// never-drawn window cannot hang a batch); (3) a victim tab at index 0 makes a
// regressed index-0 getter return the victim (!= ActiveTab) and fail. Also checks
// the ResetActiveTabIfRemoved reference no-op branch.
internal sealed class CurrentTabCouplingStep : ISelfTestStep
{
private readonly Plugin _plugin;
private bool _forcedOpen;
private int _waitFrames;
public CurrentTabCouplingStep(Plugin plugin)
{
_plugin = plugin;
}
public string Name => "Hellion Chat - CurrentTab couples to active tab";
public SelfTestStepResult RunStep()
{
// Empty-config edge: actually exercise the getter's empty-fallback (it must
// return a fresh Tab, not null/throw) rather than an unconditional pass.
if (Plugin.Config.Tabs.Count == 0)
{
if (_plugin.CurrentTab is null)
{
ImGui.Text("Empty-config getter returned null instead of a fallback Tab.");
return SelfTestStepResult.Fail;
}
ImGui.Text("No tabs configured; getter returns the empty-fallback Tab.");
return SelfTestStepResult.Pass;
}
// /xlperf usually runs without the window drawn, so ActiveTab can be null
// on the first pass. Open the window so the Draw-seed sets it, retry next
// frame, and assert unconditionally once it is non-null. Bounded so a
// never-drawn window cannot hang a batch run.
if (_plugin.MainWindow.ActiveTab is null)
{
if (!_plugin.MainWindow.IsOpen)
{
_plugin.MainWindow.Toggle();
_forcedOpen = true;
}
if (++_waitFrames > 300)
{
RestoreWindow();
ImGui.Text(
"MainWindow never drew a seed within 300 frames; coupling not asserted."
);
return SelfTestStepResult.Pass;
}
ImGui.Text("Opening window so the draw-seed can set ActiveTab; retrying...");
return SelfTestStepResult.Waiting;
}
try
{
// Insert a victim at index 0: a regressed index-0 getter would return
// THIS instead of ActiveTab, so ReferenceEquals would catch it.
var victim = new Tab { Name = "selftest-coupling-victim" };
// Insert shifts every index; the worker's DropOldestTempTab holds
// TabsListLock across its index lookup and removal.
lock (_plugin.TabsListLock)
Plugin.Config.Tabs.Insert(0, victim);
try
{
if (!ReferenceEquals(_plugin.CurrentTab, _plugin.MainWindow.ActiveTab))
{
ImGui.Text("CurrentTab is not the same reference as ActiveTab");
return SelfTestStepResult.Fail;
}
if (ReferenceEquals(_plugin.CurrentTab, victim))
{
ImGui.Text("CurrentTab returned the index-0 victim (getter still index-based)");
return SelfTestStepResult.Fail;
}
// Reference no-op: resetting against a tab that is NOT the active
// one must leave the active reference untouched.
var activeBefore = _plugin.MainWindow.ActiveTab;
_plugin.MainWindow.ResetActiveTabIfRemoved(victim);
if (!ReferenceEquals(_plugin.MainWindow.ActiveTab, activeBefore))
{
ImGui.Text("ResetActiveTabIfRemoved changed the active tab on a non-match");
return SelfTestStepResult.Fail;
}
return SelfTestStepResult.Pass;
}
finally
{
lock (_plugin.TabsListLock)
Plugin.Config.Tabs.Remove(victim);
}
}
finally
{
RestoreWindow();
}
}
private void RestoreWindow()
{
if (_forcedOpen && _plugin.MainWindow.IsOpen)
_plugin.MainWindow.Toggle();
_forcedOpen = false;
}
public void CleanUp()
{
RestoreWindow();
_waitFrames = 0;
}
}
@@ -0,0 +1,141 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
using HellionChat.Code;
using HellionChat.GameFunctions.Types;
namespace HellionChat.SelfTests;
// Guided: interactive, fires NO synthetic probes. Shows the full measured
// state every frame so a result is observable, not a guess, and walks the user
// through the real switch-away-and-back flow. It verifies the PRIVACY-relevant
// effect, keyed on the tab type:
// - a NORMAL tab carrying a game-side tell must lose its RUNTIME target
// (CurrentChannel.TellTarget) on switch-away-and-back, so a
// typed line can't /tell the old partner;
// - a BOUND auto-tell tab keeps its partner by design (leg1) — its binding is
// Tab.TellTarget and is deliberately untouched by the strip.
// The channel label is intentionally NOT asserted: a tell tab re-derives back to
// Tell after the strip ; only the target matters for privacy.
internal sealed class CurrentTabGuidedStep : ISelfTestStep
{
private readonly Plugin _plugin;
// 0 = waiting for a tell; 1 = tell seen, waiting to switch AWAY; 2 = switched
// away, waiting to come BACK to the tracked tab.
private int _phase;
private Tab? _tellTab;
private bool _wasBound;
private string _seenPartner = "";
public CurrentTabGuidedStep(Plugin plugin)
{
_plugin = plugin;
}
public string Name => "Hellion Chat - Tell target cleared on tab switch (guided)";
public SelfTestStepResult RunStep()
{
var active = _plugin.CurrentTab;
var cc = active.CurrentChannel;
var bound = active.TellTarget?.IsSet() == true;
var runtime = cc.TellTarget?.IsSet() == true;
// Live diagnostics every frame — a result is never a guess.
ImGui.Text($"Active tab : {active.Name}");
ImGui.Text($"Channel : {cc.Channel}");
ImGui.Text($"Runtime target : {DescribeTarget(cc.TellTarget)}");
ImGui.Text($"Tab-bound (leg1): {(bound ? $"yes -> {active.TellTarget!.Name}" : "no")}");
if (_tellTab is not null)
ImGui.Text(
$"Tracking '{_tellTab.Name}' (bound: {_wasBound}, partner: {_seenPartner})"
);
ImGui.Separator();
if (ImGui.Button("Skip##guided-tellflow"))
{
ImGui.Text("Skipped by user — not verified.");
return SelfTestStepResult.Pass;
}
// Restart cleanly if the tracked tab is evicted mid-flow.
if (_tellTab is not null && !Plugin.Config.Tabs.Contains(_tellTab))
{
ImGui.Text(">> Tracked tab was removed; restarting.");
Reset();
}
if (_phase == 0)
{
ImGui.Text(">> Step 1: get a tab into Tell — /tell from a normal tab (stay on it),");
ImGui.Text(" or open an auto-tell tab. Watch the lines above update.");
if (cc.Channel == InputChannel.Tell && (runtime || bound))
{
_tellTab = active;
_wasBound = bound;
_seenPartner = bound ? active.TellTarget!.Name : cc.TellTarget!.Name;
_phase = 1;
}
return SelfTestStepResult.Waiting;
}
if (_phase == 1)
{
ImGui.Text(">> Step 2: now click AWAY to a different tab.");
if (!ReferenceEquals(active, _tellTab))
_phase = 2;
return SelfTestStepResult.Waiting;
}
// _phase == 2: switched away; wait to come BACK, then check the target.
ImGui.Text($">> Step 3: now click BACK onto '{_tellTab!.Name}'.");
if (!ReferenceEquals(active, _tellTab))
return SelfTestStepResult.Waiting;
if (_wasBound)
{
// leg1: the binding lives on Tab.TellTarget and must survive the strip.
if (_tellTab.TellTarget?.IsSet() == true)
{
ImGui.Text(
"PASS: bound auto-tell tab kept its partner (leg1 — the conversation stays)."
);
return SelfTestStepResult.Pass;
}
ImGui.Text(
$"FAIL: bound tab LOST partner '{_seenPartner}' — leg1 was wrongly stripped."
);
return SelfTestStepResult.Fail;
}
// non-bound: the stale RUNTIME target must be gone (the privacy strip).
if (_tellTab.CurrentChannel.TellTarget?.IsSet() != true)
{
ImGui.Text(
$"PASS: stale partner '{_seenPartner}' cleared — a typed line won't /tell them."
);
return SelfTestStepResult.Pass;
}
ImGui.Text(
"FAIL: stale runtime partner still bound after switch-away-and-back — privacy leak."
);
return SelfTestStepResult.Fail;
}
private static string DescribeTarget(TellTarget? t) =>
t?.IsSet() == true ? $"{t.Name} (World {t.World})" : "none";
private void Reset()
{
_phase = 0;
_tellTab = null;
_wasBound = false;
_seenPartner = "";
}
public void CleanUp() => Reset();
}
+131
View File
@@ -0,0 +1,131 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
using HellionChat.Ui.Components.Settings;
using HellionChat.Util;
namespace HellionChat.SelfTests;
// The gate has fourteen unit tests. None of them prove that the workers are
// wired to it, and that is where the mistake actually happened: the metadata
// refresh reached the store without taking the gate at all, and its flag was
// missing from the tab's shared busy state, so a wipe could start while it held
// the read lock.
//
// A unit test cannot see that. It needs the real singleton, the real flags and
// the real settings tab, so it lives here.
internal sealed class DbGateWiringStep : ISelfTestStep
{
private readonly Plugin _plugin;
public DbGateWiringStep(Plugin plugin) => _plugin = plugin;
public string Name => "Hellion Chat - DB gate wiring";
public SelfTestStepResult RunStep()
{
var failures = new List<string>();
// Nothing may be running when the probe starts, or the assertions below
// measure somebody else's operation.
if (_plugin.DbOperations.IsBusy)
failures.Add($"gate already held by {_plugin.DbOperations.Current} before the probe");
CheckEveryOperationRoundTrips(failures);
CheckRefusalLeavesTheOwnerAlone(failures);
CheckRevisionTracksMutations(failures);
CheckTabSeesTheGate(failures);
foreach (var f in failures)
ImGui.Text(f);
SelfTestReport.Append(Name, failures.Count == 0 ? "PASS" : "FAIL", failures);
return failures.Count == 0 ? SelfTestStepResult.Pass : SelfTestStepResult.Fail;
}
private void CheckEveryOperationRoundTrips(List<string> failures)
{
foreach (var op in EnumValues<DbOperation>.All)
{
if (op == DbOperation.None)
continue;
if (!_plugin.DbOperations.TryBegin(op))
{
failures.Add($"{op}: TryBegin refused on a free gate");
continue;
}
if (_plugin.DbOperations.Current != op)
failures.Add($"{op}: gate reports {_plugin.DbOperations.Current} after TryBegin");
if (_plugin.DbOperations.TryBegin(op))
failures.Add($"{op}: a second TryBegin succeeded while it was held");
_plugin.DbOperations.End(op);
if (_plugin.DbOperations.IsBusy)
failures.Add($"{op}: still busy after End");
}
}
private void CheckRefusalLeavesTheOwnerAlone(List<string> failures)
{
if (!_plugin.DbOperations.TryBegin(DbOperation.Export))
{
failures.Add("could not take the gate for the refusal check");
return;
}
// A worker whose TryBegin was refused still runs its finally. Releasing
// there must not hand away somebody else's lock.
_plugin.DbOperations.End(DbOperation.Clear);
if (_plugin.DbOperations.Current != DbOperation.Export)
failures.Add("a foreign End released the gate");
_plugin.DbOperations.End(DbOperation.Export);
}
private void CheckRevisionTracksMutations(List<string> failures)
{
var before = _plugin.DbOperations.Revision;
_plugin.DbOperations.TryBegin(DbOperation.Export);
_plugin.DbOperations.End(DbOperation.Export);
if (_plugin.DbOperations.Revision != before)
failures.Add("export moved the revision; it cannot change a row");
_plugin.DbOperations.TryBegin(DbOperation.Cleanup);
_plugin.DbOperations.End(DbOperation.Cleanup);
if (_plugin.DbOperations.Revision == before)
failures.Add(
"cleanup did not move the revision; a stale preview would pass as current"
);
}
// The settings tab decides whether the destructive buttons are live. If it
// cannot see a held gate, two of them are clickable at once.
private void CheckTabSeesTheGate(List<string> failures)
{
if (!_plugin.DbOperations.TryBegin(DbOperation.Clear))
{
failures.Add("could not take the gate for the tab check");
return;
}
try
{
if (!_plugin.DataPrivacyTab.AnythingRunningForSelfTest)
failures.Add("the data and privacy tab does not see a held gate");
}
finally
{
_plugin.DbOperations.End(DbOperation.Clear);
}
if (_plugin.DataPrivacyTab.AnythingRunningForSelfTest)
failures.Add("the tab still reports busy after the gate was released");
}
public void CleanUp() { }
}
+101
View File
@@ -0,0 +1,101 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.Text;
using Dalamud.Plugin.SelfTest;
using HellionChat._Helpers;
namespace HellionChat.SelfTests;
// Proves the plugin-disclosure arm-and-hold wires the (otherwise verwaist)
// scanner into the REAL send entry InputBar.TrySend. Drives TrySend via the
// arm-test-hook with a PUA glyph in the buffer and NotifyPluginDisclosure on:
// the first send must ARM and HOLD (no send), so PendingMessage stays the probe
// string and the armed flag is set. Arm-case ONLY (seiteneffektfrei): a real
// send fires ChatBox.SendMessageUnsafe (a real in-game chat line), so the
// second-Enter-sends + ASCII-passthrough legs are in-game smoke only, never
// headless. Does NOT call PluginDisclosureScanner.ContainsPrivateUseGlyph in
// isolation (the false-green trap — it has no other production caller).
internal sealed class DisclosureArmStep : ISelfTestStep
{
private readonly Plugin plugin;
public DisclosureArmStep(Plugin plugin)
{
this.plugin = plugin;
}
public string Name => "Hellion Chat - plugin disclosure arm";
public SelfTestStepResult RunStep()
{
var input = this.plugin.InputBar;
if (input is null)
{
ImGui.Text("Plugin.InputBar is null");
return SelfTestStepResult.Fail;
}
// The SymbolPicker inserts exactly these FFXIV Private-Use-Area glyphs;
// HighQuality is inside PluginDisclosureScanner's PUA range by
// construction (the scanner range IS the SeIconChar range).
var probe = $"test {SeIconChar.HighQuality.ToIconString()} msg";
var savedPending = input.PendingMessage;
var savedNotify = Plugin.Config.NotifyPluginDisclosure;
try
{
Plugin.Config.NotifyPluginDisclosure = true;
input.TestResetDisclosureForSelfTest();
input.TestSetPendingMessageForSelfTest(probe);
// Precondition guard: refuse to drive the real TrySend unless the
// toggle is on AND the scanner sees the probe glyph. If the scanner
// regressed, this bails with Fail WITHOUT ever calling TrySend, so a
// broken scanner can never leak a real chat line. (The remaining
// risk — TrySend not calling the scanner at all — is the wiring this
// step exists to catch and is covered by the documented residual-leak
// note + the mandatory mid-cycle smoke; see the Step 4.8 warning box.)
if (
!Plugin.Config.NotifyPluginDisclosure
|| !PluginDisclosureScanner.ContainsPrivateUseGlyph(input.PendingMessage)
)
{
ImGui.Text(
"Disclosure precondition not met (toggle off or probe glyph not in the scanner's PUA range) — refusing to drive TrySend to avoid an unintended real send"
);
return SelfTestStepResult.Fail;
}
// First send with a PUA glyph + toggle on must ARM, not send. Pass a
// null Tab — the arm branch returns before any channel/send use.
var armed = input.TestTryArmDisclosureForSelfTest(null);
if (!armed)
{
ImGui.Text(
"First send did not arm disclosure for a PUA-glyph buffer (scanner not wired into TrySend?)"
);
return SelfTestStepResult.Fail;
}
// Buffer must be HELD: TrySend clears _pendingMessage to empty only on
// a real send, so an unchanged probe proves nothing was transmitted.
if (input.PendingMessage != probe)
{
ImGui.Text(
$"Buffer not held on arm: PendingMessage = '{input.PendingMessage}', expected the unchanged probe (a cleared buffer means it actually sent)"
);
return SelfTestStepResult.Fail;
}
return SelfTestStepResult.Pass;
}
finally
{
input.TestResetDisclosureForSelfTest();
input.TestSetPendingMessageForSelfTest(savedPending);
Plugin.Config.NotifyPluginDisclosure = savedNotify;
}
}
public void CleanUp() { }
}
@@ -0,0 +1,187 @@
using Dalamud.Bindings.ImGui;
using Dalamud.Game.Text;
using Dalamud.Plugin.SelfTest;
using HellionChat.Code;
using HellionChat.Export;
using HellionChat.Util;
namespace HellionChat.SelfTests;
// v1.12.0: the exporter now reads text from the chunk lists instead of the
// raw SeStrings. That change is invisible to the build suite -- ExportToFile
// takes IEnumerable<Message>, Message needs SeString, and xUnit cannot load
// Dalamud.dll, so even an empty list fails before the body runs.
//
// So it is verified here, against real messages, with the three properties that
// actually matter:
//
// 1. Text survives the round trip. If the exporter ever reads SenderSource or
// ContentSource again, a message built without them comes out blank.
// 2. The format guard runs before the file is opened. It used to run after,
// so an unknown format left a zero-byte file where a previous export had
// been.
// 3. The write is atomic. A failure partway must not leave a file that opens
// cleanly and is quietly incomplete -- this is the path a GDPR access
// request goes out on.
internal sealed class ExportRoundTripStep : ISelfTestStep
{
public string Name => "Hellion Chat - Export round trip";
public SelfTestStepResult RunStep()
{
var dir = Path.Combine(Path.GetTempPath(), $"hellionchat-selftest-{Guid.NewGuid():N}");
Directory.CreateDirectory(dir);
var failures = new List<string>();
try
{
CheckTextSurvives(dir, failures);
CheckUnknownFormatKeepsExistingFile(dir, failures);
CheckNoLeftoverPartFile(dir, failures);
}
catch (Exception e)
{
failures.Add($"threw: {e.GetType().Name}: {e.Message}");
}
finally
{
TryCleanup(dir);
}
foreach (var f in failures)
ImGui.Text(f);
SelfTestReport.Append(Name, failures.Count == 0 ? "PASS" : "FAIL", failures);
return failures.Count == 0 ? SelfTestStepResult.Pass : SelfTestStepResult.Fail;
}
private static void CheckTextSurvives(string dir, List<string> failures)
{
const string sender = "Selftest Sender";
const string content = "selftest content marker";
var path = Path.Combine(dir, "roundtrip.csv");
var written = MessageExporter.ExportToFile(
path,
ExportFormat.Csv,
[Probe(sender, content)],
new MessageExporter.FilterDescription(null, null, null, null)
);
if (written != 1)
failures.Add($"expected 1 message written, got {written}");
var text = File.ReadAllText(path);
if (!text.Contains(sender, StringComparison.Ordinal))
failures.Add("sender missing from export -- reading SeString again?");
if (!text.Contains(content, StringComparison.Ordinal))
failures.Add("content missing from export -- reading SeString again?");
// The sender filter runs inside the exporter and must see the same text.
var filtered = Path.Combine(dir, "filtered.csv");
var hits = MessageExporter.ExportToFile(
filtered,
ExportFormat.Csv,
[Probe(sender, content), Probe("Someone Else", "other")],
new MessageExporter.FilterDescription(null, null, null, "selftest sen")
);
if (hits != 1)
failures.Add($"sender filter matched {hits} messages, expected 1");
}
private static void CheckUnknownFormatKeepsExistingFile(string dir, List<string> failures)
{
var path = Path.Combine(dir, "previous.md");
File.WriteAllText(path, "an earlier export");
try
{
MessageExporter.ExportToFile(
path,
(ExportFormat)99,
[],
new MessageExporter.FilterDescription(null, null, null, null)
);
failures.Add("unknown format did not throw");
}
catch (ArgumentOutOfRangeException) { }
if (File.ReadAllText(path) != "an earlier export")
failures.Add("unknown format destroyed the existing file");
}
private static void CheckNoLeftoverPartFile(string dir, List<string> failures)
{
var path = Path.Combine(dir, "clean.json");
MessageExporter.ExportToFile(
path,
ExportFormat.Json,
[Probe("A", "b")],
new MessageExporter.FilterDescription(null, null, null, null)
);
if (!File.Exists(path))
failures.Add("export produced no file");
if (File.Exists(path + ".part"))
failures.Add("temporary file left behind after a successful export");
// Bytes, not text. File.ReadAllText strips a byte order mark while
// detecting the encoding, so a BOM that breaks every strict JSON parser
// is invisible to the check below -- and it shipped exactly that way.
var head = File.ReadAllBytes(path);
if (head.Length >= 3 && head[0] == 0xEF && head[1] == 0xBB && head[2] == 0xBF)
failures.Add("export JSON starts with a byte order mark");
// Parsed, not merely counted. The writer builds JSON by hand, and it
// shipped a build where the chat relation kinds were interpolated as
// enum names -- "source_kind":LocalPlayer -- which every parser
// rejects. A test that only checks the file exists would have passed.
try
{
using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(path));
if (!doc.RootElement.TryGetProperty("messages", out var messages))
failures.Add("export JSON has no messages array");
else if (messages.GetArrayLength() != 1)
failures.Add($"export JSON holds {messages.GetArrayLength()} messages, expected 1");
}
catch (System.Text.Json.JsonException e)
{
failures.Add($"export JSON does not parse: {e.Message}");
}
}
// Built with empty SeStrings on purpose: the whole point is that the text
// comes from the chunks.
private static Message Probe(string sender, string content)
{
static List<Chunk> Text(string s) =>
[new TextChunk(ChunkSource.Content, null, null, null, null, false, s)];
return new Message(
0,
0,
0,
new ChatCode(XivChatType.Say, 0, 0),
Text(sender),
Text(content),
new Dalamud.Game.Text.SeStringHandling.SeString(),
new Dalamud.Game.Text.SeStringHandling.SeString()
);
}
// Nothing to undo between runs: every file lives in a fresh temp directory
// that RunStep deletes in its own finally.
public void CleanUp() { }
private static void TryCleanup(string dir)
{
try
{
if (Directory.Exists(dir))
Directory.Delete(dir, recursive: true);
}
catch (IOException) { }
catch (UnauthorizedAccessException) { }
}
}
@@ -56,6 +56,20 @@ internal sealed class FontManagerCtorSmokeStep : ISelfTestStep
return SelfTestStepResult.Fail;
}
// v1.13.0: unconditional, unlike ItalicFont. Both are always built, and a
// handle that never arrives makes SimplePushedFont push nothing silently.
if (fm.SenderFont is null)
{
ImGui.Text("SenderFont handle is null");
return SelfTestStepResult.Fail;
}
if (fm.MetaFont is null)
{
ImGui.Text("MetaFont handle is null");
return SelfTestStepResult.Fail;
}
if (fm.Axis.LoadException is { } e1)
{
ImGui.Text($"Axis load exception: {e1.Message}");
@@ -86,6 +100,63 @@ internal sealed class FontManagerCtorSmokeStep : ISelfTestStep
return SelfTestStepResult.Fail;
}
if (fm.SenderFont.LoadException is { } e6)
{
ImGui.Text($"SenderFont load exception: {e6.Message}");
return SelfTestStepResult.Fail;
}
if (fm.MetaFont.LoadException is { } e7)
{
ImGui.Text($"MetaFont load exception: {e7.Message}");
return SelfTestStepResult.Fail;
}
// Assert the atlas actually finished building all required handles,
// not just that the references are non-null. FontsReady is the observable
// state the trimmed-fallback rebuild must still reach; a half-built atlas
// would pass the null/exception checks above but fail here.
if (!fm.FontsReady)
{
ImGui.Text("FontManager.FontsReady is false (atlas not fully built).");
SelfTestReport.Append(
Name,
"FAIL",
new[] { "FontsReady is false — atlas not fully built." }
);
return SelfTestStepResult.Fail;
}
// Report what was actually verified rather than a bare Pass.
// The glyph-range entry counts make the dedup visible — the cjk-fallback
// range is now a small trimmed remainder next to the large primary range.
var counts = fm.GlyphRangeLengths;
var italicState =
fm.ItalicFont is null ? "disabled (null)"
: fm.ItalicFont.Available ? "available"
: "NOT available";
var path = SelfTestReport.Append(
Name,
"PASS",
new[]
{
$"Axis available: {fm.Axis.Available}",
$"AxisItalic available: {fm.AxisItalic.Available}",
$"FontAwesome available: {fm.FontAwesome.Available}",
$"RegularFont available: {fm.RegularFont.Available}",
$"ItalicFont: {italicState}",
$"SenderFont available: {fm.SenderFont.Available} (weight {FontManager.SenderWeight:0.00})",
$"MetaFont available: {fm.MetaFont.Available}",
$"FontsReady: {fm.FontsReady}",
$"Glyph-range entries: primary={counts.Ranges}, jp={counts.JpRange}, "
+ $"cjk-fallback={counts.CjkFallback} (B1 trimmed)",
$"UseHellionFont={Plugin.Config.UseHellionFont}, ItalicEnabled={Plugin.Config.ItalicEnabled}",
}
);
ImGui.Text(
$"PASS — FontsReady, ranges primary={counts.Ranges}/jp={counts.JpRange}/"
+ $"cjk-fallback={counts.CjkFallback}. Report: {path}"
);
return SelfTestStepResult.Pass;
}
@@ -28,10 +28,18 @@ internal sealed class FontPushSmokeStep : ISelfTestStep
return SelfTestStepResult.Fail;
}
if (fm.SenderFont is null || fm.MetaFont is null)
{
ImGui.Text("SenderFont or MetaFont missing - see FontManager ctor smoke");
return SelfTestStepResult.Fail;
}
try
{
using (fm.RegularFont.Push()) { }
using (fm.FontAwesome.Push()) { }
using (fm.SenderFont.Push()) { }
using (fm.MetaFont.Push()) { }
}
catch (Exception e)
{
@@ -0,0 +1,63 @@
using System;
using Dalamud.Bindings.ImGui;
using Dalamud.Plugin.SelfTest;
using HellionChat.Ui.StyleEngine;
namespace HellionChat.SelfTests;
// GC-reserve probe for the v1.9.0 B4a refactor: GlobalStyleScope.Push runs
// once per draw frame, so its StackHandle must allocate nothing. This step drives a
// real Push()->Dispose() cycle and asserts the per-thread allocation delta is
// ~0 (not a non-null-handle check — feedback_hellion_chat_fontmanager_push_trap).
// A warm-up cycle pays the one-time JIT/first-touch cost so the measured cycle
// reflects steady state, matching the real per-frame hot path.
internal sealed class GlobalStyleScopeAllocStep : ISelfTestStep
{
// Headroom for incidental managed noise (GC bookkeeping, boxing inside
// ImGui bindings we do not control). The pre-fix path allocated ~1-2 KB
// per cycle (44 boxes + List), so anything under this threshold proves
// the StackHandle itself stopped allocating. Tighten only if a future
// binding upgrade removes all incidental noise.
private const long AllocBudgetBytes = 256;
private readonly Plugin _plugin;
public GlobalStyleScopeAllocStep(Plugin plugin)
{
_plugin = plugin;
}
public string Name => "Hellion Chat - GlobalStyleScope GC reserve";
public SelfTestStepResult RunStep()
{
var registry = _plugin.ThemeRegistry;
var theme = registry.Active;
var opacity = Plugin.Config.WindowOpacity;
// Warm-up: JIT the Push/Dispose path + first-touch any lazy ImGui
// stack growth, so the measured cycle is steady-state only.
GlobalStyleScope.Push(theme, registry, opacity).Dispose();
var before = GC.GetAllocatedBytesForCurrentThread();
GlobalStyleScope.Push(theme, registry, opacity).Dispose();
var delta = GC.GetAllocatedBytesForCurrentThread() - before;
// Report the measured figure on BOTH outcomes (a bare Pass hides
// show Pass) — the byte delta is the whole point of the GC-reserve probe.
var ok = delta <= AllocBudgetBytes;
var status = ok ? "PASS" : "FAIL";
SelfTestReport.Append(
Name,
status,
new[] { $"Push/Dispose allocated {delta} bytes/cycle (budget {AllocBudgetBytes})" }
);
ImGui.Text(
$"GlobalStyleScope.Push allocated {delta} bytes/cycle "
+ $"(budget {AllocBudgetBytes}) — {status}."
);
return ok ? SelfTestStepResult.Pass : SelfTestStepResult.Fail;
}
public void CleanUp() { }
}

Some files were not shown because too many files have changed in this diff Show More