News:

SMF - Just Installed!

Main Menu

Recent posts

#21
Duyurular ve Sürümler / v1.1.18
Last post by hitsumo - Jul 23, 2026, 03:33 PM
# Anime Tracker 1.1.18

**Yayın tarihi:** 2026-07-19

## Yeni: "Son İzlenenler" tablosunda anime posteri

- **İstatistik sayfasındaki "Son İzlenenler" tablosunda artık animenin posteri
  görünüyor.** Önceden yalnızca yazıyla anime adı vardı.
- **Her anime iki satır kaplar:** üst satırda poster ile birlikte durum, izlenen
  bölüm ve son izleme bilgileri; alt satırda animenin adı.
- **Anime adı tablonun tamamını kullanır.** Ad dar Anime sütununa
  sığdırılsaydı uzun başlıklar beş altı satıra sarardı; tam genişlikte bir iki
  satıra iner.
- **Postere de isme de tıklamak anime detayına götürür.**
- **Posteri olmayan animelerde kırık resim çıkmaz.** Poster girilmemişse
  arayüz dilinize göre "burada resim yok" / "image not here" görseli
  gösterilir; gerçek posteri eklediğinizde yerini kendiliğinden ona bırakır.
- Poster kutusu 80x120 piksel, yani tam poster oranındadır (2:3); görseller
  ezilmeden, oranı bozulmadan gösterilir.

## Düzeltme: "Son İzlenenler" tablosunda Başlık Dili çalışmıyordu

- **"Başlık Dili" tercihiniz bu tabloda dikkate alınmıyordu.** İngilizce başlık
  tercihini açmış olsanız bile "Son İzlenenler" tablosu animenin özgün adını
  gösteriyordu; ana liste ve anime detay sayfası ise doğru çalışıyordu. Artık
  bu tablo da tercihinize uyar.
- İstatistik sayfasındaki diğer tablolar (medya türü, yayın durumu, izleme
  durumu, duygu dağılımı) sayaç tablolarıdır ve anime adı göstermez; bu yüzden
  düzeltme tek tabloyu ilgilendirir.

## Temizlik: 1.1.15'ten kalan kullanılmayan iki kalem silindi

- 1.1.15'te kaldırılan mor "Hikaye: 35" rozetinden arta kalan `.marker-episode-story`
  CSS kuralı ve `anime_details.marker.story_after_episode` dil anahtarı (Türkçe
  ve İngilizce) kaldırıldı. İkisinin de projede hiçbir kullanımı kalmamıştı.
- Görünürde bir değişiklik yaratmaz; yalnızca ölü kod temizliğidir. Türkçe /
  İngilizce dil anahtarı sayısı eşit kaldı (ikisinden de aynı anahtar düştü).

## Nasıl çalışır (teknik)

- "Son İzlenenler" sorgusu artık `a.image_path` ve `a.title_english` alanlarını
  da çekiyor. İkisi de `animes` tablosunda zaten vardı, yalnızca bu sorguda
  seçilmiyordu - bu yüzden poster gösterilemiyor ve başlık dili
  uygulanamıyordu.
- Poster kaynağı mevcut `poster_src()` yardımcısıyla (1.1.9) belirlenir, başlık
  ise mevcut `display_title()` yardımcısıyla. Yeni yardımcı yazılmadı.
- Stil kuralları `statistics.php` içindeki `<style>` bloğuna eklendi; sayfanın
  mevcut deseni budur, ayrı bir CSS dosyası açılmadı.

## Şema / migration

- `migration/1.1.18/upgrade.sql` yalnızca sürümü 1.1.18'e taşır; **şema
  değişikliği yoktur** (çalıştırılacak SQL ifadesi yok). Merkez katalog
  etkilenmez, sunucuda elle bir işlem **gerekmez**.

## Değişen / yeni dosyalar

- files/statistics.php (sorguya image_path + title_english; Anime hücresinde
  poster + ad; stil bloğuna poster kuralları)
- files/css/series.css (kullanılmayan `.marker-episode-story` kuralı silindi)
- files/lang/tr.php, files/lang/en.php (kullanılmayan
  `anime_details.marker.story_after_episode` anahtarı silindi)
- files/migration/1.1.18/upgrade.sql (yeni)
- files/version.txt
#22
Announcements & Releases / v1.1.18
Last post by hitsumo - Jul 23, 2026, 03:33 PM
# Anime Tracker 1.1.18

**Release date:** 2026-07-19

## New: poster art in the "Recently Watched" table

- **The "Recently Watched" table on the statistics page now shows each anime's
  poster.** Previously the column held nothing but the name as text.
- **Each anime now spans two rows:** the poster together with watch status,
  episodes watched and last-watched time on the upper row, and the anime's name
  on the row beneath it.
- **The name uses the full width of the table.** Squeezed into the narrow Anime
  column, long titles wrapped over five or six lines; at full width they come
  down to one or two.
- **Clicking either the poster or the name opens the anime's detail page.**
- **Anime without a poster no longer risk a broken image.** When no poster has
  been set, a placeholder in your interface language is shown instead; as soon
  as you add a real poster it takes over on its own.
- The poster box is 80x120 pixels - exactly poster ratio (2:3) - so images are
  shown without being squashed or distorted.

## Fix: Title Language was ignored in the "Recently Watched" table

- **Your "Title Language" preference had no effect on this table.** Even with
  English titles turned on, "Recently Watched" kept showing the original title,
  while the main list and the detail page honoured the preference correctly.
  The table now follows your setting.
- The other tables on the statistics page (media type, broadcast status, watch
  status, emotion distribution) are counter tables and show no anime names, so
  the fix concerns this one table only.

## Cleanup: two unused leftovers from 1.1.15 removed

- The `.marker-episode-story` CSS rule and the
  `anime_details.marker.story_after_episode` language key (Turkish and English)
  were left over from the purple "Story: 35" badge that 1.1.15 removed. Neither
  had a single remaining use anywhere in the project.
- Nothing changes visually; this is dead-code cleanup only. The Turkish and
  English key counts stayed level (the same key was dropped from both).

## How it works (technical)

- The "Recently Watched" query now also selects `a.image_path` and
  `a.title_english`. Both columns already existed on the `animes` table and
  were simply not selected here - which is why the poster could not be shown
  and the title language could not be applied.
- The poster source comes from the existing `poster_src()` helper (1.1.9) and
  the title from the existing `display_title()` helper. No new helper was
  written.
- The style rules were added to the `<style>` block inside `statistics.php`,
  matching that page's existing pattern; no separate CSS file was introduced.

## Schema / migration

- `migration/1.1.18/upgrade.sql` only moves the version to 1.1.18; there is
  **no schema change** (no SQL statement to run). The central catalog is
  unaffected and **no** manual step is needed on the server.

## Changed / new files

- files/statistics.php (image_path + title_english in the query; poster and
  name in the Anime cell; poster rules in the style block)
- files/css/series.css (unused `.marker-episode-story` rule removed)
- files/lang/tr.php, files/lang/en.php (unused
  `anime_details.marker.story_after_episode` key removed)
- files/migration/1.1.18/upgrade.sql (new)
- files/version.txt
#23
Announcements & Releases / v1.1.17
Last post by hitsumo - Jul 23, 2026, 03:32 PM
# Anime Tracker 1.1.17

**Release date:** 2026-07-19

## New: Filter by country

- **The main list can now be filtered by country.** A new "Filter by Country"
  dropdown sits in the filter box, just below the broadcast-status filter. It
  combines with every other filter (genre, watch status, broadcast status,
  letter, year).
- **The dropdown is not a fixed country list: it shows only countries actually
  entered in the catalog.** If the catalog holds no Korean production, "South
  Korea" does not appear, so you cannot pick a filter that returns nothing.
  Options appear on their own as you fill the field in.
- **When no anime has a country yet**, the dropdown is replaced by a short
  "No countries recorded yet." note.
- **The adult-content preference applies here too.** With adult content off, a
  country that appears only on 18+ titles stays out of the list - the same
  behaviour as the year filter.
- **The filter survives sorting and pagination.** Changing the sort column,
  picking a letter, moving to another page or running a search does not drop
  your country selection. That includes the "By Watched Episodes" sort.

## New: Country of origin on an anime

- **The add and edit forms gained an optional "Country of Origin" field**,
  directly below Media Type.
- **The country is picked from a list, not typed.** Initial list: China,
  France, Japan, South Korea, Taiwan, United States.
- **The country name follows the interface language** - "Japan" in English,
  "Japonya" in Turkish. That is possible because the database stores the
  international country code (JP, CN, KR, ...) rather than a name. You never
  type or see the code; every screen shows the country's name.
- **A list was chosen over free text** because the catalog is shared: with free
  text one country would produce three separate filter values ("Japan",
  "japan", "Japonya") and could not be translated.
- **The anime detail page shows the country** below the broadcast dates. When
  no country is set the row is omitted entirely - no empty "Not set" line is
  added.
- **Adding a country to the list is a one-line change:** one entry in the
  `country_codes()` map in `functions/country_helpers.php` plus the country's
  name in `lang/tr.php` and `lang/en.php`.

## Existing anime

- **No existing anime is assigned a country.** The upgrade only adds the
  field; no row is stamped by guesswork. The country filter therefore starts
  out empty and fills up as you enter data.
- The reason is that the catalog can also hold Chinese and Korean productions;
  assuming "everything is Japan" would leave overlooked titles filed under the
  wrong country.

## Bulk backfill tool (one-time, optional)

- **`tek_kullanimlik/anilist_country_backfill.php`** asks AniList about every
  anime that still has no country and produces `UPDATE` statements for you to
  run. Nothing is guessed: AniList's `countryOfOrigin` is structured data in
  exactly the form we store (ISO 3166-1 alpha-2).
- **It does not touch the database.** You review the generated SQL and run it
  in phpMyAdmin yourself:
  `php anilist_country_backfill.php > country_backfill.sql`
- **It cannot overwrite a country you entered by hand** - it only queries rows
  where `country IS NULL`, and the generated `UPDATE` carries the same
  condition.
- **A code outside the country list is reported, never written.** An unmapped
  code in the database would make that anime invisible to every filter. You
  decide whether to add the country to the list and re-run.
- Limit: only anime carrying a `mal_id` can be matched. Unmatched rows and rows
  without a `mal_id` are reported as counts and stay manual.

## AniList import now brings the country with it

- **Every anime imported from AniList arrives with its country.** AniList
  already exposes `countryOfOrigin`; the import query now asks for it and
  carries the value into the record. A donghua you import is born in the
  catalog as "China" instead of waiting to be filled in later.
- This applies both online (written to the suggestion row, passed into the
  catalog on moderator approval) and self-host (written straight to the local
  record).
- **A code outside the country list is not written; the field is left empty.**
  Storing an unmapped code would make that anime invisible to every filter.
- MyAnimeList (XML) imports carry no country data, so titles from that path
  stay country-less and are filled in by hand or with the bulk tool.

## Where the country travels

Country is catalog data about the anime, and it is preserved everywhere the
data moves:

- **Pushing to and pulling from the central catalog** (online mode).
- **Backup export / restore** (self-host). The backup file carries the
  country; backups taken before 1.1.17 have no such field, so those rows are
  restored without one.
- **Member suggestions and moderator approval.** A suggestion row can carry a
  country, and approval passes it into the catalog.

## Schema / migration

- `migration/1.1.17/upgrade.sql` adds the `country` column to `animes` and
  `catalog_requests` (`char(2)`, NULL = no country entered) and bumps the
  version to 1.1.17. A duplicate-column error on re-run is ignored.
- **Manual step for the central catalog (online only):** the central catalog
  database is a separate installation with no automatic migration runner.
  Before pushing country data to it, run this once on the central catalog DB:
  `ALTER TABLE animes ADD COLUMN country CHAR(2) DEFAULT NULL AFTER media_type;`
  Pushing before that is done makes the request fail. Order matters: this
  statement on the server first, then the application update, then the push.
  Self-host installs are unaffected (the local migration runs on its own).

## Changed / new files

- files/migration/1.1.17/upgrade.sql (new: country column, two tables)
- files/schema.sql (column for fresh installs; animes + catalog_requests)
- files/functions/country_helpers.php (new: country_codes / country_label /
  country_options / country_sort_key / is_valid_country_code)
- files/functions.php (load the new helper)
- files/tek_kullanimlik/anilist_country_backfill.php (new: one-time bulk
  backfill tool; emits SQL, never writes to the DB)
- files/index.php (list of countries present in the catalog; country filter
  box; the filter predicate is added to `select_from` so the "By Watched
  Episodes" sort branch inherits it; selection preserved across sort, letter,
  year and search links)
- files/add_anime.php, files/edit_anime.php (Country of Origin dropdown; code
  validated before saving)
- files/anime_details.php (country row; omitted when empty)
- files/functions/anilist_import_helpers.php (countryOfOrigin in the import
  query; country on the entry - an unmapped code is left empty)
- files/list_settings.php (carry country through backup restore, member
  suggestion creation, and both branches of the AniList import)
- files/catalog_import.php, files/admin/catalog_push.php,
  files/admin/admin_sync_example.php, files/admin/admin_catalog_requests.php,
  catalog_server/catalog.php, catalog_server/admin_push.php
  (country across the catalog wire format)
- files/lang/tr.php, files/lang/en.php (country names; form and filter labels;
  detail-page label)
- files/version.txt

Note: country names are sorted according to the interface language. In the
Turkish UI "Çin" lands correctly between "C" and "D"; PHP's default comparison
would push that letter to the end of the list, so the ordering follows the
Turkish alphabet explicitly.
#24
Announcements & Releases / v1.1.16
Last post by hitsumo - Jul 23, 2026, 03:32 PM
# Anime Tracker 1.1.16

**Release date:** 2026-07-17

## New: Interface language choice for non-member visitors

- **Signed-out visitors can now choose the interface language.** In
  multi-user (online) mode a visitor without an account previously saw the
  interface in Turkish only, with no way to change it. They can now switch
  between **Turkish / English**.
- **The choice is made from a small language switcher on the sign-in /
  register / request-invite pages.** It is a dropdown at the top-right, above
  the page card; picking a language switches the interface to it instantly.
- **The choice persists for the session.** Once selected, it applies across
  every page you visit for the rest of your browser session; you do not have
  to pick it again on each page.
- **Nothing changes for signed-in users or self-host (single-user)
  installs.** They still choose the interface language from the "Interface
  Language" section on the "List Settings" page; this small switcher is not
  shown to them.

## New: The registration announcement is now per language

- **The registration-screen announcement (register.php) can now be written
  separately in Turkish and English.** Previously there was a single text that
  showed regardless of the selected language; the admin panel (Invites) now has
  two fields: "Announcement text (Turkish)" and "Announcement text (English)".
- **If the English field is left empty, the Turkish announcement is shown on
  the English interface too.** So for an operator who writes a single-language
  announcement, behaviour is unchanged - it shows in both languages. An
  operator who fills both fields gives each interface its own language-specific
  text.

## Change: Email is now required when generating an invite

- **An email address is now required when generating an invite code.**
  Previously it was "(optional)" and could be left blank, which left it unclear
  who each invite was for. Every invite is now tied to a recipient email.
- **The invite is still sent manually - no automatic email is sent.** The email
  only records who the invite is for; you deliver the code to that person
  yourself. Submitting "Generate code" with an empty or invalid email creates
  no code and the form shows a warning.

## How it works (technical)

- A signed-in user's language preference is stored in the `user_pref` table.
  Because an anonymous visitor has no user id (and therefore no `user_pref`
  row), the choice is kept in the PHP session (`$_SESSION`) instead.
  `lang_init()` reads the guest choice from the session; `set_language.php`
  writes it there. The `set_language.php` endpoint, its form shape and its
  CSRF protection are unchanged.
- The guest switcher is produced by the `guest_lang_switcher()` helper, which
  returns HTML only when the visitor is "multi-user mode + not signed in";
  in every other case it returns an empty string, so pages look exactly as
  before. It reuses the same translation keys as the settings-page switcher
  (no new copy was added).

## Schema / migration

- `migration/1.1.16/upgrade.sql` only advances the version to 1.1.16; **there
  is no schema change** (no SQL statement to run). The fix lives entirely in
  the application layer. The central catalog is unaffected and no manual step
  is required on the server.

## Changed / new files

- functions/i18n_helpers.php (lang_init: read the guest language from the
  session; new `guest_lang_switcher()` helper)
- set_language.php (write the guest choice to the session instead of
  `user_pref`)
- login.php, register.php, request_invite.php (show the guest language
  switcher; register/request_invite: `.auth-alt` links styled as buttons)
- register.php (registration announcement: Turkish/English text by selected
  language, falling back to Turkish when the English text is empty)
- admin/admin_invites.php (a second, English text field for the announcement;
  saving writes both fields at once - email required when generating an invite:
  server-side validation + form `required` + warning on invalid submit)
- lang/admin_tr.php, lang/admin_en.php (English announcement field labels:
  announce.label / label_en / placeholder_en / hint_en; invite email strings:
  generate.desc / email_label / err_email)
- css/lang.css (guest language switcher styles; the file emptied in 1.1.4 now
  holds one rule again)
- migration/1.1.16/upgrade.sql (new)
- version.txt

Note: the English announcement text is stored under the `register_announcement_en`
settings key. The `settings` table is a key-value store and the row is created
on first save; no new table/column is required (no schema change).
#25
Duyurular ve Sürümler / v1.1.17
Last post by hitsumo - Jul 23, 2026, 03:31 PM
# Anime Tracker 1.1.17

**Yayın tarihi:** 2026-07-19

## Yeni: Ülkeye göre filtreleme

- **Ana listede artık ülkeye göre filtreleme yapılabilir.** Filtre kutusunda,
  yayın durumu filtresinin hemen altında yeni bir "Ülkeye Göre Filtrele"
  açılır kutusu vardır. Seçim, diğer filtrelerle (tür, izleme durumu, yayın
  durumu, harf, yıl) birlikte çalışır.
- **Açılır kutu sabit bir ülke listesi değildir: yalnızca katalogda gerçekten
  girilmiş ülkeleri gösterir.** Katalogda hiç Kore yapımı yoksa "Güney Kore"
  seçeneği görünmez, dolayısıyla boş sonuç veren bir filtre seçmeniz mümkün
  olmaz. Siz animelere ülke girdikçe seçenekler kendiliğinden belirir.
- **Hiçbir animede ülke girilmemişse** açılır kutu yerine "Henüz kayıtlı ülke
  yok." bilgisi görünür.
- **Yetişkin içerik tercihi burada da geçerlidir.** Yetişkin içerik kapalıyken,
  yalnızca +18 animelerde geçen bir ülke listede görünmez - yıl filtresindeki
  davranışın aynısı.
- **Filtre, sıralama ve sayfalama gezinirken korunur.** Sütun başlığına
  tıklayıp sıralamayı değiştirdiğinizde, harf seçtiğinizde, sayfa
  değiştirdiğinizde veya arama yaptığınızda ülke seçiminiz düşmez. Bu,
  "İzlenen Bölüme Göre" sıralaması için de geçerlidir.

## Yeni: Anime kaydında yapım ülkesi

- **Anime ekleme ve düzenleme formlarına "Yapım Ülkesi" alanı eklendi**
  (opsiyonel). Medya Türü alanının hemen altındadır.
- **Ülke listeden seçilir, elle yazılmaz.** Başlangıç listesi: Amerika
  Birleşik Devletleri, Çin, Fransa, Güney Kore, Japonya, Tayvan.
- **Ülke adı arayüz diline göre görünür.** Türkçe arayüzde "Japonya",
  İngilizce arayüzde "Japan" yazar. Bunun sebebi, veritabanında ülke adının
  değil uluslararası ülke kodunun (JP, CN, KR ...) saklanmasıdır. Kodu ne
  girersiniz ne de görürsünüz; her yerde ülkenin adı gösterilir.
- **Serbest metin yerine liste kullanılmasının nedeni** katalogun ortak
  olmasıdır: serbest yazımda aynı ülke "Japonya", "Japan" ve "japonya" olarak
  üç ayrı filtre değeri üretir ve dil desteği mümkün olmazdı.
- **Anime detay sayfasında ülke, yayın tarihi bilgilerinin altında gösterilir.**
  Ülke girilmemişse satır hiç basılmaz - "Belirtilmemiş" yazan boş bir satır
  eklenmez.
- **Listeye yeni ülke eklemek tek satırlık bir iştir:**
  `functions/country_helpers.php` içindeki `country_codes()` haritasına bir
  satır ve `lang/tr.php` + `lang/en.php` dosyalarına ülkenin adı eklenir.

## Mevcut animeler

- **Mevcut animelerin hiçbirine ülke atanmaz.** Sürüm yükseltmesi yalnızca
  alanı ekler; hiçbir satır tahmin yoluyla damgalanmaz. Dolayısıyla ülke
  filtresi ilk açılışta boş görünür ve siz doldurdukça dolar.
- Bunun nedeni, katalogda Çin ve Kore yapımı animelerin de bulunabilmesidir;
  "hepsi Japonya" varsayımı gözden kaçan yapımları yanlış ülkede bırakırdı.

## Toplu doldurma aracı (tek seferlik, isteğe bağlı)

- **`tek_kullanimlik/anilist_country_backfill.php`**, ülkesi boş olan animeleri
  AniList'e sorup size çalıştırılacak `UPDATE` cümleleri üretir. Ülke bilgisi
  tahmin edilmez: AniList'in `countryOfOrigin` alanı zaten bizim sakladığımız
  biçimde (ISO 3166-1 alpha-2) yapısal veri verir.
- **Veritabanına dokunmaz.** Ürettiği SQL'i inceleyip phpMyAdmin'de siz
  çalıştırırsınız:
  `php anilist_country_backfill.php > country_backfill.sql`
- **Elle girdiğiniz ülkeleri ezmez** - yalnızca `country IS NULL` satırları
  sorgular, ürettiği `UPDATE` de aynı koşulu taşır.
- **Ülke listesinde olmayan bir kod dönerse yazılmaz**, ayrıca raporlanır.
  Tanımlı olmayan bir kod veritabanına girseydi o anime hiçbir filtrede
  görünmezdi. Raporu görüp o ülkeyi listeye eklemek isteyip istemediğinize
  siz karar verirsiniz.
- Sınır: yalnızca `mal_id` taşıyan animeler eşleşir. Eşleşmeyenler ve
  `mal_id`'si olmayanlar sayı olarak raporlanır, elle doldurulur.

## AniList içe aktarma artık ülkeyi kendisi getirir

- **AniList'ten içe aktarılan her anime ülkesiyle birlikte gelir.** AniList
  `countryOfOrigin` alanını zaten veriyor; içe aktarma sorgusu artık bu alanı
  da istiyor ve değeri kayda taşıyor. Yani içe aktardığınız bir donghua
  katalogda doğrudan "Çin" olarak doğar, sonradan doldurulmayı beklemez.
- Bu hem online (öneri kaydına yazılır, moderatör onayında kataloğa geçer) hem
  self-host (yerel kayda doğrudan yazılır) tarafında geçerlidir.
- **Ülke listesinde olmayan bir kod gelirse yazılmaz, alan boş bırakılır.**
  Tanımsız bir kod kaydedilseydi o anime hiçbir filtrede görünmezdi.
- MyAnimeList (XML) içe aktarmasında ülke bilgisi yoktur; o yoldan gelen
  animeler ülkesiz kalır ve elle ya da toplu doldurma aracıyla tamamlanır.

## Ülke bilgisi taşınan yollar

Ülke, animeye ait bir katalog bilgisidir ve verinin dolaştığı her yolda
korunur:

- **Merkez kataloğa gönderme ve merkez katalogdan çekme** (online mod).
- **Yedek alma / geri yükleme** (self-host). Yedek dosyası ülkeyi içerir;
  1.1.17 öncesinde alınmış yedeklerde alan bulunmadığı için o kayıtlar ülkesiz
  geri yüklenir.
- **Üye önerisi ve moderatör onayı.** Öneri kaydı ülkeyi taşıyabilir ve onayda
  kataloğa aktarılır.

## Şema / migration

- `migration/1.1.17/upgrade.sql`, `animes` ve `catalog_requests` tablolarına
  `country` kolonunu ekler (`char(2)`, NULL = ülke girilmemiş) ve sürümü
  1.1.17'ye yükseltir. Tekrar çalıştırmada yinelenen-kolon hatası yok sayılır.
- **Merkez katalog için elle adım (yalnızca online):** merkez katalog
  veritabanı ayrı bir kurulumdur ve otomatik migration çalıştırıcısı yoktur.
  Ülke bilgisini oraya göndermeden önce merkez katalog DB'sinde bir kez
  çalıştırın:
  `ALTER TABLE animes ADD COLUMN country CHAR(2) DEFAULT NULL AFTER media_type;`
  Bu yapılmadan gönderim denenirse istek hata verir. Sıra önemlidir: önce
  sunucuda bu komut, sonra uygulama güncellemesi, sonra gönderim. Self-host
  kurulumları etkilenmez (yerel migration kendiliğinden çalışır).

## Değişen / yeni dosyalar

- files/migration/1.1.17/upgrade.sql (yeni: country kolonu, iki tablo)
- files/schema.sql (yeni kurulum için kolon; animes + catalog_requests)
- files/functions/country_helpers.php (yeni: country_codes / country_label /
  country_options / country_sort_key / is_valid_country_code)
- files/functions.php (yeni yardımcı dosyayı yükle)
- files/tek_kullanimlik/anilist_country_backfill.php (yeni: tek seferlik toplu
  doldurma aracı; DB'ye yazmaz, SQL üretir)
- files/index.php (katalogda geçen ülkelerin listesi; ülke filtresi kutusu;
  filtre koşulu `select_from`'a eklendi - böylece "İzlenen Bölüme Göre"
  sıralama dalı da aynı koşulu alır; sıralama/harf/yıl/arama bağlantılarında
  seçimin korunması)
- files/add_anime.php, files/edit_anime.php (Yapım Ülkesi açılır kutusu; kayıt
  öncesi kod doğrulaması)
- files/anime_details.php (ülke satırı; boşsa gösterilmez)
- files/functions/anilist_import_helpers.php (içe aktarma sorgusuna
  countryOfOrigin; kayda country alanı - tanınmayan kod boş bırakılır)
- files/list_settings.php (yedek geri yüklemede, üye önerisi oluşturmada ve
  AniList içe aktarmanın her iki dalında ülkeyi taşı)
- files/catalog_import.php, files/admin/catalog_push.php,
  files/admin/admin_sync_example.php, files/admin/admin_catalog_requests.php,
  catalog_server/catalog.php, catalog_server/admin_push.php
  (katalog veri formatı boyunca country)
- files/lang/tr.php, files/lang/en.php (ülke adları; form ve filtre etiketleri;
  anime detay etiketi)
- files/version.txt

Not: ülke adlarının sıralaması arayüz diline göre yapılır. Türkçe arayüzde
"Çin", "C" ile "D" arasında doğru yerde çıkar; PHP'nin varsayılan
karşılaştırması bu harfi listenin sonuna atacağı için sıralama Türk
alfabesine göre ayrıca düzenlenmiştir.
#26
Duyurular ve Sürümler / v1.1.16
Last post by hitsumo - Jul 23, 2026, 03:30 PM
# Anime Tracker 1.1.16

**Release date:** 2026-07-17

## New: Interface language choice for non-member visitors

- **Signed-out visitors can now choose the interface language.** In
  multi-user (online) mode a visitor without an account previously saw the
  interface in Turkish only, with no way to change it. They can now switch
  between **Turkish / English**.
- **The choice is made from a small language switcher on the sign-in /
  register / request-invite pages.** It is a dropdown at the top-right, above
  the page card; picking a language switches the interface to it instantly.
- **The choice persists for the session.** Once selected, it applies across
  every page you visit for the rest of your browser session; you do not have
  to pick it again on each page.
- **Nothing changes for signed-in users or self-host (single-user)
  installs.** They still choose the interface language from the "Interface
  Language" section on the "List Settings" page; this small switcher is not
  shown to them.

## New: The registration announcement is now per language

- **The registration-screen announcement (register.php) can now be written
  separately in Turkish and English.** Previously there was a single text that
  showed regardless of the selected language; the admin panel (Invites) now has
  two fields: "Announcement text (Turkish)" and "Announcement text (English)".
- **If the English field is left empty, the Turkish announcement is shown on
  the English interface too.** So for an operator who writes a single-language
  announcement, behaviour is unchanged - it shows in both languages. An
  operator who fills both fields gives each interface its own language-specific
  text.

## Change: Email is now required when generating an invite

- **An email address is now required when generating an invite code.**
  Previously it was "(optional)" and could be left blank, which left it unclear
  who each invite was for. Every invite is now tied to a recipient email.
- **The invite is still sent manually - no automatic email is sent.** The email
  only records who the invite is for; you deliver the code to that person
  yourself. Submitting "Generate code" with an empty or invalid email creates
  no code and the form shows a warning.

## How it works (technical)

- A signed-in user's language preference is stored in the `user_pref` table.
  Because an anonymous visitor has no user id (and therefore no `user_pref`
  row), the choice is kept in the PHP session (`$_SESSION`) instead.
  `lang_init()` reads the guest choice from the session; `set_language.php`
  writes it there. The `set_language.php` endpoint, its form shape and its
  CSRF protection are unchanged.
- The guest switcher is produced by the `guest_lang_switcher()` helper, which
  returns HTML only when the visitor is "multi-user mode + not signed in";
  in every other case it returns an empty string, so pages look exactly as
  before. It reuses the same translation keys as the settings-page switcher
  (no new copy was added).

## Schema / migration

- `migration/1.1.16/upgrade.sql` only advances the version to 1.1.16; **there
  is no schema change** (no SQL statement to run). The fix lives entirely in
  the application layer. The central catalog is unaffected and no manual step
  is required on the server.

## Changed / new files

- functions/i18n_helpers.php (lang_init: read the guest language from the
  session; new `guest_lang_switcher()` helper)
- set_language.php (write the guest choice to the session instead of
  `user_pref`)
- login.php, register.php, request_invite.php (show the guest language
  switcher; register/request_invite: `.auth-alt` links styled as buttons)
- register.php (registration announcement: Turkish/English text by selected
  language, falling back to Turkish when the English text is empty)
- admin/admin_invites.php (a second, English text field for the announcement;
  saving writes both fields at once - email required when generating an invite:
  server-side validation + form `required` + warning on invalid submit)
- lang/admin_tr.php, lang/admin_en.php (English announcement field labels:
  announce.label / label_en / placeholder_en / hint_en; invite email strings:
  generate.desc / email_label / err_email)
- css/lang.css (guest language switcher styles; the file emptied in 1.1.4 now
  holds one rule again)
- migration/1.1.16/upgrade.sql (new)
- version.txt

Note: the English announcement text is stored under the `register_announcement_en`
settings key. The `settings` table is a key-value store and the row is created
on first save; no new table/column is required (no schema change).
#27
Announcements & Releases / v1.1.15
Last post by hitsumo - Jul 19, 2026, 03:30 AM
# Anime Tracker 1.1.15

**Release date:** 2026-07-17

## New: Story order for chronology

- **A chronology marker can now carry two insertion points.** Until now a
  marker only recorded where a related anime (a film, OVA, ...) sits in
  **release order** - the point where it actually aired. A marker can now also
  carry a **story order** point: where it is best watched in the narrative.
  Example: the first Card Captor Sakura film aired after episode 46 but is
  recommended after episode 35.
- **You only fill the second number when it differs.** If a marker's story
  point is left empty it is treated as "same as release", so existing markers
  need no change and appear at the same spot in both orders. You add a story
  point only to the markers that actually diverge.
- **A single button switches the view: release → story → both.** On the anime
  detail page (the chronology notes list) and on the Chronology page, one
  button cycles through showing the release order, the story order, or both
  orders one under the other. Clicking it changes the current view only for
  your session; it does not overwrite your saved default.
- **A saved default in List Settings.** A new "Chronology View" preference
  chooses which order opens by default: release (the default), story, or both.
  It is per-user and affects only you.
- **Both points are editable inline on existing markers.** Next to each row in
  the notes list, a small field adjusts that row's episode: the release-order
  list edits the release point, the story-order list edits the story point
  (empty clears it) - without deleting and re-creating the marker. The two boxes
  are independent; changing one does not move the other.

## Unchanged behaviour

- **The active "watch this next" alert still follows release order only.** The
  reminder that appears on the detail page as you progress is unchanged; the new
  story order is a listing/view feature, not a second alert.

## How it works (technical)

- A new nullable column `chronology_markers.story_after_episode` holds the story
  point. `NULL` means "no divergence"; the story view falls back to the release
  point with `COALESCE(story_after_episode, after_episode)`. The column is
  deliberately **not** part of the marker's UNIQUE KEY, so a catalog re-push
  updates it through `ON DUPLICATE KEY UPDATE`.
- The display mode (release / story / both) is resolved as: an ephemeral session
  override (the cycle button) first, then the saved per-user preference
  (`chrono_display_mode`), then `release`. The button posts to
  `set_chrono_mode.php`; List Settings posts the same endpoint with `persist=1`
  to write the saved default and clear the session override.
- The story point travels through the full catalog wire format, so it is shared
  with all users like the rest of a marker: local push, server store, catalog
  pull/import, the member catalog-request path and admin approval all carry it.

## Schema / migration

- `migration/1.1.15/upgrade.sql` adds the `story_after_episode` column to
  `chronology_markers` (a single `ALTER TABLE`; a duplicate-column re-run is
  ignored) and advances the version to 1.1.15.
- **Central catalog manual step (online only):** the central catalog database is
  a separate install and has no automatic migration runner. Before pushing story
  points to it, run once on the central catalog DB:
  `ALTER TABLE chronology_markers ADD COLUMN story_after_episode INT NULL AFTER after_episode;`
  Until this is done the server keeps every story point as NULL; self-host
  installs are unaffected (their local migration runs automatically).

## Changed / new files

- files/migration/1.1.15/upgrade.sql (new: story_after_episode column)
- files/schema.sql (column + comment for a fresh install)
- files/functions/series_helpers.php (getChronologyMarkers order param;
  chrono_current_mode / chrono_next_mode / chrono_display_modes / chrono_mode_label)
- files/add_chronology_marker.php (accept + validate story_after_episode)
- files/update_chronology_marker.php (new: set/clear story point on a marker)
- files/set_chrono_mode.php (new: cycle button + persist=1 default)
- files/anime_details.php (story field in the add form; both-number display;
  inline story edit; cycle button; mode-aware marker list)
- files/chronology.php (mode-aware timeline; "both" = two labelled lists; cycle button)
- files/list_settings.php (Chronology View default preference; story in the
  backup export/import marker payload)
- files/catalog_import.php, files/admin/catalog_push.php,
  files/admin/admin_catalog_requests.php, files/admin/admin_sync_example.php,
  catalog_server/catalog.php, catalog_server/admin_push.php
  (story_after_episode across the catalog wire format)
- files/help/help_series.php, files/lang/tr.php, files/lang/en.php
  (release/story labels, mode button, settings, help text)
- files/css/series.css (cycle button, section labels, inline edit)
- files/version.txt
#28
Duyurular ve Sürümler / v1.1.15
Last post by hitsumo - Jul 19, 2026, 03:29 AM
# Anime Tracker 1.1.15

**Yayın tarihi:** 2026-07-17

## Yeni: Kronolojide hikaye sırası

- **Bir kronoloji işareti artık iki ekleme noktası taşıyabilir.** Şimdiye
  kadar bir işaret, ilgili animenin (film, OVA, ...) yalnızca **yayın
  sırasındaki** yerini (gerçekte çıktığı bölüm) tutuyordu. Artık bir işaret
  ayrıca bir **hikaye sırası** noktası da taşıyabilir: anlatı içinde izlenmesi
  önerilen bölüm. Örnek: ilk Card Captor Sakura filmi 46. bölümden sonra çıktı
  ama 35. bölümden sonra izlenmesi önerilir.
- **İkinci sayıyı yalnızca farklıysa girersiniz.** Bir işaretin hikaye noktası
  boş bırakılırsa "yayınla aynı" kabul edilir; böylece mevcut işaretler
  değişmez ve iki sırada da aynı yerde görünür. Hikaye noktasını yalnızca
  gerçekten ayrışan işaretlere eklersiniz.
- **Tek düğme görünümü değiştirir: yayın → hikaye → ikisi.** Anime detay
  sayfasında (kronoloji notları listesi) ve Kronoloji sayfasında tek bir düğme
  sırayla yayın sırasını, hikaye sırasını ya da ikisini alt alta gösterir.
  Düğmeye tıklamak yalnızca o oturumdaki görünümü değiştirir; kaydettiğiniz
  varsayılanı ezmez.
- **Liste Ayarları'nda kayıtlı varsayılan.** Yeni "Kronoloji Görünümü" tercihi
  hangi sıranın varsayılan açılacağını belirler: yayın (varsayılan), hikaye ya
  da ikisi. Kişi bazlıdır, yalnızca sizi etkiler.
- **İki nokta da mevcut işaretlerde satır içinde düzenlenebilir.** Notlar
  listesinde her satırın yanındaki küçük alan o satırın bölümünü ayarlar:
  Yayın Sırası listesi yayın noktasını, Hikaye Sırası listesi hikaye noktasını
  (boş bırakınca temizlenir) düzenler — işareti silip yeniden oluşturmaya gerek
  kalmadan. İki kutu bağımsızdır; birini değiştirmek diğerini etkilemez.

## Değişmeyen davranış

- **Aktif "sırada bunu izle" uyarısı hâlâ yalnızca yayın sırasına göre
  çalışır.** İlerledikçe detay sayfasında çıkan hatırlatma değişmedi; yeni
  hikaye sırası bir listeleme/görünüm özelliğidir, ikinci bir uyarı değil.

## Nasıl çalışır (teknik)

- Yeni ve boş olabilen `chronology_markers.story_after_episode` kolonu hikaye
  noktasını tutar. `NULL` "ayrışma yok" demektir; hikaye görünümü
  `COALESCE(story_after_episode, after_episode)` ile yayın noktasına düşer.
  Kolon bilerek işaretin UNIQUE anahtarına dahil **edilmedi**, böylece katalog
  yeniden push'unda `ON DUPLICATE KEY UPDATE` ile güncellenir.
- Görünüm modu (yayın / hikaye / ikisi) şu sırayla çözülür: geçici oturum
  değeri (döngü butonu), ardından kayıtlı kişisel tercih
  (`chrono_display_mode`), ardından `release`. Düğme `set_chrono_mode.php`'ye
  POST eder; Liste Ayarları aynı endpoint'e `persist=1` ile POST ederek kalıcı
  varsayılanı yazar ve oturum değerini temizler.
- Hikaye noktası tüm katalog wire format'ından geçer, böylece işaretin geri
  kalanı gibi tüm kullanıcılarla paylaşılır: yerel push, sunucu kaydı, katalog
  çekme/içe aktarma, üye katalog-isteği yolu ve admin onayı hepsi taşır.

## Şema / migration

- `migration/1.1.15/upgrade.sql`, `chronology_markers` tablosuna
  `story_after_episode` kolonunu ekler (tek bir `ALTER TABLE`; tekrar
  çalıştırmada yinelenen-kolon hatası yok sayılır) ve sürümü 1.1.15'e yükseltir.
- **Merkez katalog için elle adım (yalnızca online):** merkez katalog
  veritabanı ayrı bir kurulumdur ve otomatik migration çalıştırıcısı yoktur.
  Hikaye noktalarını oraya göndermeden önce merkez katalog DB'sinde bir kez
  çalıştırın:
  `ALTER TABLE chronology_markers ADD COLUMN story_after_episode INT NULL AFTER after_episode;`
  Bu yapılana kadar sunucu her hikaye noktasını NULL tutar; self-host
  kurulumları etkilenmez (yerel migration otomatik çalışır).

## Değişen / yeni dosyalar

- files/migration/1.1.15/upgrade.sql (yeni: story_after_episode kolonu)
- files/schema.sql (yeni kurulum için kolon + açıklama)
- files/functions/series_helpers.php (getChronologyMarkers sıralama parametresi;
  chrono_current_mode / chrono_next_mode / chrono_display_modes / chrono_mode_label)
- files/add_chronology_marker.php (story_after_episode al + doğrula)
- files/update_chronology_marker.php (yeni: işaretin hikaye noktasını set/temizle)
- files/set_chrono_mode.php (yeni: döngü butonu + persist=1 varsayılan)
- files/anime_details.php (ekleme formunda hikaye alanı; iki-nokta gösterimi;
  satır içi hikaye düzenleme; döngü butonu; mod-duyarlı marker listesi)
- files/chronology.php (mod-duyarlı timeline; "ikisi" = iki başlıklı liste; döngü butonu)
- files/list_settings.php (Kronoloji Görünümü tercihi; yedek export/import
  marker payload'ında story)
- files/catalog_import.php, files/admin/catalog_push.php,
  files/admin/admin_catalog_requests.php, files/admin/admin_sync_example.php,
  catalog_server/catalog.php, catalog_server/admin_push.php
  (katalog wire format boyunca story_after_episode)
- files/help/help_series.php, files/lang/tr.php, files/lang/en.php
  (yayın/hikaye etiketleri, mod butonu, ayarlar, yardım metni)
- files/css/series.css (döngü butonu, bölüm başlıkları, satır içi düzenleme)
- files/version.txt
#29
Announcements & Releases / v1.1.14
Last post by hitsumo - Jul 19, 2026, 03:28 AM
# Anime Tracker 1.1.14

**Release date:** 2026-07-17

## New: Filter by year

- **The main list page gains a "Filter by Year" filter.** A collapsible
  section, sitting between the broadcast-status filter and the letter filter,
  holds a grid of year checkboxes.
- **You can pick a single year or several.** Check just one year (e.g. 1972),
  a few years at once (e.g. 1972 + 1973), or non-contiguous years
  (e.g. 1972 + 1986 + 2004). Every anime whose year is among those selected is
  listed.
- **The years are generated automatically from the catalog.** The years in the
  boxes are not a hand-maintained list; they are derived from each anime's
  release date (`release_date`) and sorted descending. Add an anime from a new
  year and that year's checkbox appears on its own; remove the last anime of a
  year and the box disappears on its own. (Only anime with a release date are
  included in a year box.)
- **The selected year is highlighted instantly.** Checking a box fills the chip
  blue; unchecking turns it white immediately - so you see the current
  selection clearly even before pressing "Filter".
- **A "Clear year selection" button.** When a year filter is active, a button
  appears below the year section that clears only the year selection in one
  click, while preserving your other filters (search, genre, watch status,
  letter, emotion, page size, active tab).
- **The filter keeps your current search, sort and pagination.** The selected
  years are preserved as you move between sort links, the letter filter and
  page numbers.

## Improvement: help pages "back" link

- **The "Back to Home" / "Help Contents" links on the help pages now look like
  buttons.** They render as an outlined button instead of plain blue text, and
  the leading arrow was removed. Their behaviour is unchanged.

## Housekeeping

- **Two dead files removed:** `files/user_anime_helpers.php` (it had become a
  byte-for-byte duplicate of `functions/user_anime_helpers.php` and was
  referenced from nowhere) and `files/dizin_listesi.txt` (an old directory-dump
  artifact). When updating a server install you may delete these two files if
  present; there is no functional impact.

## How it works (technical)

- The filter is selected with the `year_filter[]` array parameter. Year is not
  a separate column; the predicate runs on the existing `animes.release_date`
  column as `YEAR(a.release_date) IN (...)`. No new table, column or setting is
  needed.
- Selected year values are cast to `(int)` on the server and whitelisted
  against the years that actually exist in the catalog; only validated integers
  are embedded in the SQL, so there is no injection surface.
- The chip highlight is bound to the live checkbox state rather than a
  server-side class (`:has(input:checked)` plus a small JS sync), so unchecking
  removes the highlight instantly.

## Schema / migration

- `migration/1.1.14/upgrade.sql` only advances the version to 1.1.14; there is
  **no schema change** (no SQL statement to run). The central catalog is not
  affected and requires no manual step.

## Changed / new files

- index.php (Filter by year: parameter parsing, `YEAR(release_date) IN (...)`
  predicate in both query branches, selected years preserved across
  sort/letter/pagination links, filter-form UI, chip-sync JS)
- css/series.css (year grid and chip styles, "Clear year selection" button)
- css/help.css (button look for the help-page "back" link)
- lang/tr.php, lang/en.php (index.filter.year / year_none / year_clear keys;
  removal of the leading arrow from help.back_to_home / back_to_index)
- migration/1.1.14/upgrade.sql (new)
- version.txt
- Removed: files/user_anime_helpers.php, files/dizin_listesi.txt
#30
Duyurular ve Sürümler / v1.1.14
Last post by hitsumo - Jul 19, 2026, 03:27 AM
# Anime Tracker 1.1.14

**Yayin tarihi:** 2026-07-17

## Yeni: Yila gore filtre

- **Ana liste sayfasina "Yila Gore Filtrele" filtresi eklendi.** Yayin durumu
  filtresi ile harf filtresi arasinda duran, acilir-kapanir bir bolum icinde
  yil onay kutulari (checkbox) yer alir.
- **Tek ya da birden cok yil secebilirsiniz.** Sadece tek bir yili
  (orn. 1972) isaretleyebilir, birkac yili birden (orn. 1972 + 1973) ya da
  bitisik olmayan yillari (orn. 1972 + 1986 + 2004) ayni anda secebilirsiniz.
  Secili yillari iceren tum animeler listelenir.
- **Yillar katalogtan otomatik gelir.** Kutulardaki yillar elle tutulan bir
  liste degildir; katalogdaki animelerin yayin tarihinden (`release_date`)
  turetilir ve azalan sirada dizilir. Yeni bir yila ait anime eklediginizde
  o yilin kutusu kendiliginden ortaya cikar; o yila ait anime kalmazsa kutu
  kendiliginden kaybolur. (Yalniz yayin tarihi girili animeler bir yil
  kutusuna dahil olur.)
- **Secili yil aninda vurgulanir.** Bir kutuyu isaretlediginizde cip mavi
  dolar, isareti kaldirdiginizda aninda beyaza doner - "Filtrele"ye basmadan
  once bile secili durumu net gorursunuz.
- **"Yil secimini temizle" butonu.** Aktif bir yil filtresi varken yil
  bolumunun altinda cikan bu buton, diger filtrelerinizi (arama, tur, izleme
  durumu, harf, duygu, sayfa boyutu, aktif sekme) koruyarak yalnizca yil
  secimini tek tiklamada temizler.
- **Filtre mevcut aramanizi, siralamanizi ve sayfalamanizi korur.** Secili
  yillar; siralama baglantilari, harf filtresi ve sayfa numaralari arasinda
  gezerken korunur.

## Iyilestirme: Yardim sayfalarindaki "geri don" baglantisi

- **Yardim sayfalarindaki "Ana Sayfaya Don" / "Yardim Icindekiler"
  baglantilari artik buton gorunumunde.** Duz mavi yazi yerine cerceveli buton
  olarak gorunur; basindaki ok isareti kaldirildi. Islevi degismedi.

## Temizlik

- **Iki olu dosya kaldirildi:** `files/user_anime_helpers.php` (artik
  `functions/user_anime_helpers.php` ile birebir ayni bir kopyaydi ve hicbir
  yerden cagrilmiyordu) ve `files/dizin_listesi.txt` (eski bir dizin dokumu
  artefakti). Sunucuya kurulumu guncellerken bu iki dosya varsa elle
  silinebilir; islevsel bir etkisi yoktur.

## Nasil calisir (teknik)

- Filtre `year_filter[]` dizi parametresiyle secilir. Yil ayri bir kolon
  degildir; predikat mevcut `animes.release_date` kolonu uzerinde
  `YEAR(a.release_date) IN (...)` olarak calisir. Yeni tablo, alan veya ayar
  gerekmez.
- Secilen yil degerleri sunucuda `(int)`'e cast edilir ve yalnizca katalogda
  gercekten bulunan yillarla eslesecek sekilde beyaz listeye alinir; SQL'e
  yalnizca dogrulanmis tamsayilar gomulur, boylece enjeksiyon yuzeyi yoktur.
- Cip vurgusu sunucu tarafi bir sinifa degil canli checkbox durumuna baglidir
  (`:has(input:checked)` + kucuk bir JS senkronu), bu yuzden isareti
  kaldirinca vurgu aninda kalkar.

## Sema / migration

- `migration/1.1.14/upgrade.sql` yalnizca surumu 1.1.14'e tasir; **sema
  degisikligi yoktur** (calistirilacak SQL ifadesi yok). Merkez katalog
  etkilenmez, sunucuda elle bir islem GEREKMEZ.

## Degisen / yeni dosyalar

- index.php (Yila gore filtre: parametre ayristirma, iki sorgu dalinda
  `YEAR(release_date) IN (...)` predikati, secili yillarin siralama/harf/
  sayfalama baglantilarinda korunmasi, filtre formu arayuzu, cip senkron JS'i)
- css/series.css (yil izgarasi ve cip stilleri, "Yil secimini temizle" butonu)
- css/help.css (yardim sayfasi "geri don" baglantisinin buton gorunumu)
- lang/tr.php, lang/en.php (index.filter.year / year_none / year_clear
  anahtarlari; help.back_to_home / back_to_index metinlerinden ok isaretinin
  kaldirilmasi)
- migration/1.1.14/upgrade.sql (yeni)
- version.txt
- Kaldirildi: files/user_anime_helpers.php, files/dizin_listesi.txt