Skip to content

Commit

Permalink
[foundryvtt#1964] Add method to localize schemas in ArrayFields
Browse files Browse the repository at this point in the history
Adds a static `localize` method to activities which performs
pre-localization tasks. During the `i18nInit` hook the system
iterates over all activities and calls this method.

This method calls the normal `localizeDataModel` method on the
activity itself and then calls `Activity#_localizeSchema` to
localize any `SchemaField`s in arrays (this method is necessary
because core's `localizeSchema` method is private).
  • Loading branch information
arbron committed Aug 2, 2024
1 parent 65b1d55 commit 01b6bac
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 31 deletions.
4 changes: 1 addition & 3 deletions dnd5e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,7 @@ function expandAttributeList(attributes) {
*/
Hooks.once("i18nInit", () => {
utils.performPreLocalization(CONFIG.DND5E);
Localization.localizeDataModel(dnd5e.documents.activity.AttackActivity);
Localization.localizeDataModel(dnd5e.documents.activity.SummonActivity);
Localization.localizeDataModel(dnd5e.documents.activity.UtilityActivity);
Object.values(CONFIG.DND5E.activityTypes).forEach(c => c.documentClass.localize());
});

/* -------------------------------------------- */
Expand Down
45 changes: 42 additions & 3 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,32 @@
},
"targets": {
"label": "Consumption Targets",
"hint": "Targets of possible consumption when this activity is activated."
"hint": "Targets of possible consumption when this activity is activated.",
"FIELDS": {
"type": {
"label": "Consumption Type",
"hint": "Type of consumption target."
},
"target": {
"label": "Consumption Target",
"hint": "Specific target to be consumed."
},
"value": {
"label": "Consumption Amount",
"hint": "Amount to consume of the target."
},
"scaling": {
"label": "Consumption Scaling",
"mode": {
"label": "Scaling Mode",
"hint": "How consumption should be scaled."
},
"formula": {
"label": "Scaling Formula",
"hint": "Custom scaling of consumption amount per level."
}
}
}
}
},
"duration": {
Expand Down Expand Up @@ -2041,7 +2066,7 @@
},
"profiles": {
"label": "Summons Profiles",
"*": {
"FIELDS": {
"count": {
"label": "Count"
},
Expand Down Expand Up @@ -2297,7 +2322,21 @@
},
"recovery": {
"label": "Use Recovery",
"hint": "Recovery profiles for this activity's uses."
"hint": "Recovery profiles for this activity's uses.",
"FIELDS": {
"period": {
"label": "Recovery Period",
"hint": "Time when this recovery will occur."
},
"type": {
"label": "Recovery Type",
"hint": "How uses are recovered."
},
"formula": {
"label": "Recovery Formula",
"hint": "Formula used to determine how many uses are recovered."
}
}
},
"spent": {
"label": "Spent Uses",
Expand Down
14 changes: 1 addition & 13 deletions module/data/activity/base-activity.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,6 @@ const {
* @property {string} effect ID of the effect to apply.
*/

/**
* Data for a recovery profile for an activity's uses.
*
* @typedef {object} UsesRecoveryData
* @property {string} period Period at which this profile is activated.
* @property {string} type Whether uses are reset to full, reset to zero, or recover a certain number of uses.
* @property {string} formula Formula used to determine recovery if type is not reset.
*/

/**
* Data model for activities.
*
Expand Down Expand Up @@ -75,10 +66,7 @@ const {
* @property {boolean} target.affects.choice When targeting an area, can the user choose who it affects?
* @property {string} target.affects.special Description of special targeting.
* @property {boolean} target.prompt Should the player be prompted to place the template?
* @property {object} uses
* @property {number} uses.spent Number of uses that have been spent.
* @property {string} uses.max Formula for the maximum number of uses.
* @property {UsesRecoveryData[]} uses.recovery Recovery profiles for this activity's uses.
* @property {UsesField} uses Uses available to this activity.
*/
export default class BaseActivityData extends foundry.abstract.DataModel {

Expand Down
13 changes: 13 additions & 0 deletions module/data/shared/uses-field.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,21 @@ import FormulaField from "../fields/formula-field.mjs";

const { ArrayField, NumberField, SchemaField, StringField } = foundry.data.fields;

/**
* Data for a recovery profile for an activity's uses.
*
* @typedef {object} UsesRecoveryData
* @property {string} period Period at which this profile is activated.
* @property {string} type Whether uses are reset to full, reset to zero, or recover a certain number of uses.
* @property {string} formula Formula used to determine recovery if type is not reset.
*/

/**
* Field for storing uses data.
*
* @property {number} spent Number of uses that have been spent.
* @property {string} max Formula for the maximum number of uses.
* @property {UsesRecoveryData[]} recovery Recovery profiles for this activity's uses.
*/
export default class UsesField extends SchemaField {
constructor(fields={}, options={}) {
Expand Down
26 changes: 26 additions & 0 deletions module/documents/activity/mixin.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,32 @@ export default Base => class extends PseudoDocumentMixin(Base) {
}
});

/* -------------------------------------------- */

/**
* Perform the pre-localization of this data model.
*/
static localize() {
Localization.localizeDataModel(this);
const fields = this.schema.fields;
if ( fields.damage?.fields.parts ) this._localizeSchema(fields.damage.fields.parts.element, ["DND5E.DAMAGE"]);
this._localizeSchema(fields.consumption.fields.targets.element, ["DND5E.ACTIVITY.FIELDS.consumption.targets"]);
this._localizeSchema(fields.uses.fields.recovery.element, ["DND5E.USES.FIELDS.uses.recovery"]);
}

/* -------------------------------------------- */

/**
* Perform pre-localization on the contents of a SchemaField. Necessary because the `localizeSchema` method
* on `Localization` is private.
* @param {SchemaField} schema
* @param {string[]} prefixes
* @internal
*/
static _localizeSchema(schema, prefixes) {
Localization.localizeDataModel({ schema }, { prefixes });
}

/* -------------------------------------------- */
/* Properties */
/* -------------------------------------------- */
Expand Down
8 changes: 8 additions & 0 deletions module/documents/activity/summon.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,12 @@ export default class SummonActivity extends ActivityMixin(SummonActivityData) {
sheetClass: SummonSheet
}, { inplace: false })
);

/* -------------------------------------------- */

/** @inheritDoc */
static localize() {
super.localize();
this._localizeSchema(this.schema.fields.profiles.element, ["DND5E.SUMMON.FIELDS.profiles"]);
}
}
20 changes: 11 additions & 9 deletions templates/activity/parts/damage-parts.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,37 @@
<div class="formula flexrow">
{{#unless data.custom.enabled}}

{{ formField fields.number name=(concat prefix "number") value=data.number }}
{{ formField fields.number name=(concat prefix "number") value=data.number stacked=true hint=false }}
{{ formField fields.denomination name=(concat prefix "denomination") value=data.denomination
options=denominationOptions }}
options=denominationOptions stacked=true hint=false }}
<span class="seperator">+</span>
{{ formField fields.bonus name=(concat prefix "bonus") value=data.bonus }}
{{ formField fields.bonus name=(concat prefix "bonus") value=data.bonus stacked=true hint=false }}
<input type="hidden" name="{{ prefix }}custom.formula" value="{{ data.custom.formula }}">

{{else}}

{{ formField fields.custom.fields.formula name=(concat prefix "custom.formula")
value=data.custom.formula }}
value=data.custom.formula stacked=true hint=false }}
<input type="hidden" name="{{ prefix }}number" value="{{ data.number }}">
<input type="hidden" name="{{ prefix }}denomination" value="{{ data.denomination }}">
<input type="hidden" name="{{ prefix }}bonus" value="{{ data.bonus }}">

{{/unless}}
{{ formField fields.custom.fields.enabled name=(concat prefix "custom.enabled")
value=data.custom.enabled }}
value=data.custom.enabled stacked=true hint=false }}
</div>
{{ formField fields.types name=(concat prefix "types") value=data.types options=typeOptions }}
{{ formField fields.types name=(concat prefix "types") value=data.types options=typeOptions hint=false }}

{{#if canScale}}
{{#with fields.scaling.fields as |fields|}}
<div class="scaling flexrow">
{{ formField fields.mode name=(concat ../prefix "scaling.mode") value=../data.scaling.mode
options=../scalingOptions }}
options=../scalingOptions stacked=true hint=false }}
{{#if ../data.scaling.mode}}
{{ formField fields.number name=(concat ../prefix "scaling.number") value=../data.scaling.number }}
{{ formField fields.formula name=(concat ../prefix "scaling.formula") value=../data.scaling.formula }}
{{ formField fields.number name=(concat ../prefix "scaling.number") value=../data.scaling.number
stacked=true hint=false }}
{{ formField fields.formula name=(concat ../prefix "scaling.formula") value=../data.scaling.formula
stacked=true hint=false }}
{{/if}}
</div>
{{/with}}
Expand Down
6 changes: 3 additions & 3 deletions templates/activity/parts/summon-profiles.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<div class="drop-area">{{ localize "DND5E.SUMMON.Profile.DropHint" }}</div>{{/if}}
{{/if}}
{{ formInput fields.name name=(concat prefix "name") value=data.name placeholder=(ifThen
document document.name (localize "DND5E.SUMMON.FIELDS.profiles.*.name.label")) }}
document document.name (localize "DND5E.SUMMON.FIELDS.profiles.FIELDS.name.label")) }}
<!-- aria-label="{{ localize 'Name' }}" -->
<div class="list-controls">
<button type="button" class="unbutton" data-action="deleteProfile"
Expand All @@ -62,7 +62,7 @@
{{ formField fields.types name=(concat prefix "types") value=data.types options=typeOptions }}
{{/if}}
<div class="form-group">
<label>{{ localize "DND5E.SUMMON.FIELDS.profiles.*.level.label" }}</label>
<label>{{ localize "DND5E.SUMMON.FIELDS.profiles.FIELDS.level.label" }}</label>
<div class="form-fields">
{{ formInput fields.level.fields.min name=(concat prefix "level.min")
value=data.level.min placeholder="0" }}
Expand All @@ -72,7 +72,7 @@
value=data.level.max placeholder="" }}
<!-- aria-label="{{ localize 'DND5E.LevelLimit.Max' }}" -->
</div>
<p class="hint">{{ localize "DND5E.SUMMON.FIELDS.profiles.*.level.hint" }}</p>
<p class="hint">{{ localize "DND5E.SUMMON.FIELDS.profiles.FIELDS.level.hint" }}</p>
</div>
</div>
</div>
Expand Down

0 comments on commit 01b6bac

Please sign in to comment.